This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/Html.class.php'
<?php
class Html{
public static function clean($data){
$data = $data ? str_replace("\\","\\\\",$data):'';
require_once SDK_DIR.'HtmlPurifier/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.Encoding', 'UTF-8');
$config->set('CSS.AllowTricky', true);
$config->set('Attr.EnableID', true); // 允许id
$config->set('HTML.Trusted', true); // 影响iframe过滤;
$config->set('Cache.SerializerPath', TEMP_PATH);// 缓存目录;
$config->set('Cache.DefinitionImpl', null);
$config->set('HTML.TargetBlank', FALSE);
$config->set('HTML.TargetNoreferrer', FALSE);
$config->set('HTML.TargetNoopener', FALSE);
// $config->set('HTML.SafeIframe',true);// iframe包含页面白名单;
// $config->set('URI.SafeIframeRegexp', '%^https://(*)%');
// 设置保留的标签
$config->set('HTML.Allowed','*[id|style|class|title|border|width|height|title|alt|type|data-exp|rowspan|colspan],div,b,strong,i,em,a[href|target],ul,ol,ol[start],li,p,br,span,img[src],pre,hr,code,h1,h2,h3,h4,h5,h6,blockquote,del,table,thead,tbody,tr,th,td,s,sub,sup,ins,del,address,iframe[frameborder|src|allowfullscreen|scrolling],var,mark,wbr,section,nav,article,aside,header,footer,hgroup,figure,figcaption,video[src|controls|poster],source[src]');
// data|data-exp|contenteditable|aria-hidden
// 不限制css的key;
// $config->set('CSS.AllowedProperties','font,font-size,font-weight,font-style,font-family,margin,width,height,text-decoration,padding-left,padding-top,padding-right,padding-top,padding-bottom,line-height,color,background,background-color,text-align,border-collapse,list-style-type,list-style,top,left,right,bottom,position');
$def = $config->getHTMLDefinition(true);
$def->addElement('section', 'Block', 'Flow', 'Common');
$def->addElement('nav', 'Block', 'Flow', 'Common');
$def->addElement('article', 'Block', 'Flow', 'Common');
$def->addElement('aside', 'Block', 'Flow', 'Common');
$def->addElement('header', 'Block', 'Flow', 'Common');
$def->addElement('footer', 'Block', 'Flow', 'Common');
$def->addElement('hgroup', 'Block', 'Required: h1 | h2 | h3 | h4 | h5 | h6','Common');
$def->addElement('figure', 'Block', 'Optional: (figcaption, Flow) | (Flow, figcaption) | Flow','Common');
$def->addElement('figcaption', 'Inline', 'Flow', 'Common');
$def->addElement('var', 'Inline', 'Flow', 'Common');
$def->addElement('mark', 'Inline', 'Flow', 'Common');
$def->addElement('wbr', 'Inline', 'Flow', 'Core');
$def->addElement('source','Block', 'Flow', 'Common',array('src'=>'URI','type'=>'Text'));
$def->addElement('video', 'Block', 'Flow', 'Common',array(
'src' => 'URI','type' => 'Text','width' => 'Length','height' => 'Length',
'poster' => 'URI','preload' => 'Enum#auto,metadata,none','controls' => 'Bool',
));
$def->addAttribute('a','target','Text');
$def->addAttribute('iframe','allowfullscreen','Text');
$def->addAttribute('div', 'data-exp','Text');
$def->addAttribute('span','data-exp','Text');
$def->addAttribute('div', 'style','Text');
$def->addAttribute('span','style','Text');// 重定义style属性; 不过滤style内容;
$def->addAttribute('td','style','Text');
$def->addAttribute('td','rowspan','Text');
$def->addAttribute('td','colspan','Text');
$cleanObj = new HTMLPurifier($config);
return $cleanObj->purify($data);
}
public static function onlyImage($data){
require_once SDK_DIR.'HtmlPurifier/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.SerializerPath', TEMP_PATH);// 缓存目录;
$config->set('Cache.DefinitionImpl', null);
$config->set('HTML.Allowed','img[src|alt]');
$cleanObj = new HTMLPurifier($config);
return $cleanObj->purify($data);
}
public static function clearSVG($content){
return self::removeXXS($content);
}
// 正则替换掉onload,等属性; style无法保留
public static function removeXXS($val){
// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
// this prevents some character re-spacing such as <java\0script>
// note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
$val = $val ? str_replace("\\","\\\\",$val):'';
$val = preg_replace('/([\x00-\x08\x0b-\x0c\x0e-\x19])/', '', $val);// 去除逗号;
// straight replacements, the user should never need these since they're normal characters
// this prevents like <IMG SRC=@avascript:alert('XSS')>
$search = 'abcdefghijklmnopqrstuvwxyz';
$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$search .= '1234567890!@#$%^&*()';
$search .= '~`";:?+/={}[]-_|\'\\';
for ($i = 0; $i < strlen($search); $i++) {
// ;? matches the ;, which is optional
// 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
// @ @ search for the hex values
$val = preg_replace('/(&#[xX]0{0,8}' . dechex(ord($search[$i])) . ';?)/i', $search[$i], $val); // with a ;
// @ @ 0{0,7} matches '0' zero to seven times
$val = preg_replace('/(�{0,8}' . ord($search[$i]) . ';?)/', $search[$i], $val); // with a ;
}
// now the only remaining whitespace attacks are \t, \n, and \r
$ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
$ra1 = array('javascript', 'vbscript', 'expression','script');// 过多,误判
$ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
$ra = array_merge($ra1, $ra2);
$found = true; // keep replacing as long as the previous round replaced something
while ($found == true) {
$val_before = $val;
for ($i = 0; $i < sizeof($ra); $i++) {
$pattern = '/';
for ($j = 0; $j < strlen($ra[$i]); $j++) {
if ($j > 0) {
$pattern .= '(';
$pattern .= '(&#[xX]0{0,8}([9ab]);)';
$pattern .= '|';
$pattern .= '|(�{0,8}([9|10|13]);)';
$pattern .= ')*';
}
$pattern .= $ra[$i][$j];
}
$pattern .= '/i';
$replacement = substr($ra[$i], 0, 2) . '_' . substr($ra[$i], 2); // add in <> to nerf the tag
$val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
if ($val_before == $val) {
// no replacements were made, so exit the loop
$found = false;
}
}
}
//屏蔽危险data-url, iframe/a...; src="data:text/html; href="data:text/html,...
$val = preg_replace("/\s+(src|href)\s*=(\s*[\"']\s*data\s*:\s*(text|application)\/)/i",' _$1_=$2', $val);
$val = preg_replace("/\s+srcdoc\s*=/i",' _srcdoc_=', $val);// 屏蔽iframe srcdoc
return $val;
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/I18n.class.php'
<?php
function LNG($key){
static $isInit = false;
if (func_num_args() == 1) {
return I18n::get($key);
} else {
$args = func_get_args();
array_shift($args);
return vsprintf(I18n::get($key), $args);
}
}
class I18n{
private static $loaded = false;
private static $lang = NULL;
public static $langType = NULL;
public static function load(){}
public static function defaultLang(){
if(isset($GLOBALS['config']['settings']['language'])){
return $GLOBALS['config']['settings']['language'];
}
$langDefault = 'zh-CN';//zh-CN en;
$lang = $langDefault;
$arr = $GLOBALS['config']['settingAll']['language'];
$langs = array();
foreach ($arr as $key => $value) {
$langs[$key] = $key;
}
$langs['zh'] = 'zh-CN'; //增加大小写对应关系
$langs['zh-tw'] = 'zh-TW';
$acceptLanguage = array();
if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
$httpLang = $langDefault;
}else{
$httpLang = str_replace("_","-",strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
}
preg_match_all('~([-a-z]+)(;q=([0-9.]+))?~',$httpLang,$matches,PREG_SET_ORDER);
foreach ($matches as $match) {
$acceptLanguage[$match[1]] = (isset($match[3]) ? $match[3] : 1);
}
arsort($acceptLanguage);
foreach ($acceptLanguage as $key => $q) {
if (isset($langs[$key])) {
$lang = $langs[$key];break;
}
$key = preg_replace('~-.*~','', $key);
if (!isset($acceptLanguage[$key]) && isset($langs[$key])) {
$lang = $langs[$key];break;
}
}
return $lang;
}
public static function getAll(){
self::init();
return self::$lang;
}
public static function getType(){
self::init();
return self::$langType;
}
public static function init(){
if(self::$loaded) return;
if(isset($GLOBALS['in']['language'])){
return self::setLanguage($GLOBALS['in']['language']);
}
$cookieLang = 'kodUserLanguage';
if (isset($_COOKIE[$cookieLang])) {
$lang = $_COOKIE[$cookieLang];
}else{
$lang = self::defaultLang();
}
//兼容旧版本
if($lang == 'zh_CN') $lang = 'zh-CN';
if($lang == 'zh_TW') $lang = 'zh-TW';
if(isset($GLOBALS['config']['settings']['language'])){
$lang = $GLOBALS['config']['settings']['language'];
}
self::setLanguage($lang);
}
private static function setLanguage($lang){
if(!preg_match('/^[0-9a-zA-z_\-]+$/', $lang)){
$lang = 'zh-CN';
}
$langFile = LANGUAGE_PATH.$lang.'/index.php';
if(!file_exists($langFile)){//allow remove some I18n folder
$lang = 'zh-CN';
$langFile = LANGUAGE_PATH.$lang.'/index.php';
}
self::$langType = $lang;
self::$lang = include($langFile);
self::$loaded = true;
$GLOBALS['L'] = &self::$lang;
}
public static function get($key){
self::init();
if(!isset(self::$lang[$key])) return $key;
if (func_num_args() == 1) {
return self::$lang[$key];
} else {
$args = func_get_args();
array_shift($args);
return vsprintf(self::$lang[$key], $args);
}
}
/**
* 添加多语言;
* @param [type] $args [description]
*/
public static function set($array,$value=''){
self::init();
if(is_string($array)){
return self::$lang[$array] = $value;
}
if(!is_array($array)) return;
foreach ($array as $key => $value) {
self::$lang[$key] = $value;
}
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/IpLocation.class.php'
<?php
/**
* ip地址库转换
* 数据更新:https://gitee.com/lionsoul/ip2region
*/
class IpLocation {
public static function get($ip){
if(!$ip) return LNG('common.unknow');
static $obj;
if(!$obj){
$path = dirname(__FILE__).'/Ip2Region/';
require $path.'Ip2Region.php';
$obj = new Ip2Region($path.'Ip2Region.db');
}
if(count(explode(':',$ip)) > 2) return 'IPV6';
$address = $obj->memorySearch($ip);// memorySearch/btreeSearch
return self::parseAddress($address['region']);
}
public static function parseAddress($address){
static $addressReplace;
$replaceFrom = array('中国|','0|','|','省 ');
$replaceTo = array('','',' ','省');
$lang = I18n::getType();
if( strstr($lang,'zh') ){
$replace = $lang == 'zh-TW' ? '內網IP' : '内网IP';
$address = str_replace($replaceFrom,$replaceTo,$address);
$address = str_replace('内网IP 内网IP',$replace,$address);
return $address;
}
if(!$addressReplace){
$addressMap = require(dirname(__FILE__).'/Ip2Region/'.'Address.lang.php');
$replaceFrom = array_keys($addressMap);$replaceTo = array();
usort($replaceFrom,'strLengthSort');$replaceFrom = array_reverse($replaceFrom);
foreach($replaceFrom as $key){
$replaceTo[] = $addressMap[$key];
}
$addressReplace['from'] = $replaceFrom;
$addressReplace['to'] = $replaceTo;
}
$replaceFrom = $addressReplace['from'];
$replaceTo = $addressReplace['to'];
$address = str_replace(array('0|','|0','|'),array(',',',',','),$address);
$address = str_replace(',,',',',$address);
$address = trim($address,'0');$address = trim($address,',');
$address = str_replace($replaceFrom,$replaceTo,$address);
$address = str_replace('Local IP,Local IP','Local IP',$address);
return $address;
}
}
function strLengthSort($a,$b){
$la = strlen( $a); $lb = strlen( $b);
if( $la == $lb) return strcmp( $a,$b);
return $la - $lb;
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/Mailer.class.php'
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
class Mailer {
function __construct() {
require_once __DIR__ . '/Mailer/src/Exception.class.php';
require_once __DIR__ . '/Mailer/src/PHPMailer.class.php';
// require_once __DIR__ . '/Mailer/src/POP3.class.php';
require_once __DIR__ . '/Mailer/src/SMTP.class.php';
}
/**
* 发送邮件
* 'address' => '', // 收件人
'replay' => '', // 回复人
'cc' => '', // 抄送
'bcc' => '', // 秘密抄送
'subject' => '', // 主题
'content' => '', // 内容
'html' => '' // 是否为html
* @param array $data
*/
public function send ($data) {
$config = $this->getConfig($data);
if(isset($config['code']) && !$config['code']) return $config;
$mail = new PHPMailer(true);
try {
if(i18n::getType() == 'zh-CN') {
$mail->setLanguage('zh_cn', __DIR__ . '/Mailer/language/');
}
//Server settings
// $mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
if ($config['smtp']) $mail->isSMTP(); // Send using SMTP
$mail->Host = $config['host']; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = $config['email']; // SMTP username
$mail->Password = $config['password']; // SMTP password
$mail->SMTPSecure = $config['secure'];
// if (!$mail->SMTPSecure) $mail->SMTPAutoTLS = false; // 默认自动启用tls加密
$mail->Port = $config['port']; // 不同服务提供的端口不同,总体包含:25、465、587、2525
$mail->CharSet = 'UTF-8';
// 忽略证书验证
if (!$config['secure']) {
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
}
$mail->setFrom($config['email'], $config['signature']);
//Recipients
foreach ($config['addList'] as $address) {
$mail->addAddress($address); // 收件人
}
if (!empty($data['replay'])) {
$mail->addReplyTo($data['replay']); // 回复人
}
foreach ($config['ccList'] as $address) {
$mail->addCC($address); // 抄送
}
foreach ($config['bccList'] as $address) {
$mail->addBCC($address); // 暗抄送
}
// // 附件
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
$mail->Subject = $data['subject'];
if(!empty($data['html'])){
$mail->isHTML(true); // Set email format to HTML
$mail->Body = $data['content'];
}else{
$mail->AltBody = $data['content'];
}
if($mail->send()) return array('code' => true);
return array('code' => false, 'data' => LNG('User.Regist.sendFail'));
} catch (Exception $e) {
return array('code' => false, 'data' => $mail->ErrorInfo);
}
}
public function getConfig($data){
$result = array(
'addList' => explode(';', $data['address']), // 收件人列表
'ccList' => isset($data['cc']) ? explode(';', $data['cc']) : array(), // 抄送
'bccList' => isset($data['bcc']) ? explode(';', $data['bcc']) : array(), // 暗抄送
);
if(!isset($data['email'])) {
if(!$email = Model('SystemOption')->get('email')){
return array('code' => false, 'data' => LNG('User.Regist.emailSetError'));
}
$data = array_merge($data, $email);
}
// 允许自定义端口
$parts = parse_url($data['host']);
$data['smtp'] = _get($data, 'smtp', 1) == '2' ? false : true;
$data['host'] = isset($parts['host']) ? $parts['host'] : $parts['path'];
$data['port'] = isset($parts['port']) ? $parts['port'] : 465;
if(empty($data['secure']) || $data['secure'] == 'ssl') { // 为空是兼容旧版
$data['secure'] = PHPMailer::ENCRYPTION_SMTPS;
}else if($data['secure'] == 'tls') {
$data['secure'] = PHPMailer::ENCRYPTION_STARTTLS;
}else{
$data['secure'] = false;
}
if(!isset($data['signature'])) $data['signature'] = 'kodbox';
return array_merge($data, $result);
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/MyCaptcha.class.php'
<?php
class MyCaptcha{
var $keystring;
function __construct($length){
$alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"; # do not change without changing font files!
$width = 140;
$height = 60;
$fluctuation_amplitude = $height/10;//上下起伏
$white_noise_density=1/10;//$white_noise_density=0; // no white noise
$black_noise_density=1/100;//$black_noise_density=0; // no black noise
$foreground_color = array(mt_rand(0,120), mt_rand(0,120), mt_rand(0,120));
$background_color = array(mt_rand(220,255), mt_rand(220,255), mt_rand(220,255));
$font_path = dirname(__FILE__).'/MyCaptcha_fonts/';
$fonts=array($font_path.'font_1.png',$font_path.'font_2.png',$font_path.'font_3.png');
$alphabet_length=strlen($alphabet);
do{
$this->keystring = $this->randString($length);
$font_file=$fonts[mt_rand(0, count($fonts)-1)];
$font=imagecreatefrompng($font_file);
imagealphablending($font, true);
$fontfile_width=imagesx($font);
$fontfile_height=imagesy($font)-1;
$font_metrics=array();
$symbol=0;
$reading_symbol=false;
// loading font
for($i=0;$i<$fontfile_width && $symbol<$alphabet_length;$i++){
$transparent = (imagecolorat($font, $i, 0) >> 24) == 127;
if(!$reading_symbol && !$transparent){
$font_metrics[$alphabet[$symbol]]=array('start'=>$i);
$reading_symbol=true;
continue;
}
if($reading_symbol && $transparent){
$font_metrics[$alphabet[$symbol]]['end']=$i;
$reading_symbol=false;
$symbol++;
continue;
}
}
$img=imagecreatetruecolor($width, $height);
imagealphablending($img, true);
$white=imagecolorallocate($img, 255, 255, 255);
$black=imagecolorallocate($img, 0, 0, 0);
imagefilledrectangle($img, 0, 0, $width-1, $height-1, $white);
$x=1;
$odd=mt_rand(0,1);
if($odd==0) $odd=-1;
for($i=0;$i<$length;$i++){
$m=$font_metrics[$this->keystring[$i]];
$y=(($i%2)*$fluctuation_amplitude - $fluctuation_amplitude/2)*$odd
+ mt_rand(-round($fluctuation_amplitude/3), round($fluctuation_amplitude/3))
+ ($height-$fontfile_height)/2;
$shift=1;
imagecopy($img, $font, $x-$shift, $y, $m['start'], 1, $m['end']-$m['start'], $fontfile_height);
$x+=$m['end']-$m['start']-$shift;
}
}while($x>=$width-10); // while not fit in canvas
//noise
$white=imagecolorallocate($font, 255, 255, 255);
$black=imagecolorallocate($font, 0, 0, 0);
for($i=0;$i<(($height-30)*$x)*$white_noise_density;$i++){
imagesetpixel($img, mt_rand(0, $x-1), mt_rand(10, $height-15), $white);
}
for($i=0;$i<(($height-30)*$x)*$black_noise_density;$i++){
imagesetpixel($img, mt_rand(0, $x-1), mt_rand(10, $height-15), $black);
}
$center=$x/2;
// credits. To remove, see configuration file
$img2=imagecreatetruecolor($width, $height);
$foreground=imagecolorallocate($img2, $foreground_color[0], $foreground_color[1], $foreground_color[2]);
$background=imagecolorallocate($img2, $background_color[0], $background_color[1], $background_color[2]);
imagefilledrectangle($img2, 0, 0, $width-1, $height-1, $background);
imagefilledrectangle($img2, 0, $height, $width-1, $height+12, $foreground);
$this->drawLine($img2,$width,$height);
// periods
$rand1=mt_rand(750000,1200000)/10000000;
$rand2=mt_rand(750000,1200000)/10000000;
$rand3=mt_rand(750000,1200000)/10000000;
$rand4=mt_rand(750000,1200000)/10000000;
// phases
$rand5=mt_rand(0,31415926)/10000000;
$rand6=mt_rand(0,31415926)/10000000;
$rand7=mt_rand(0,31415926)/10000000;
$rand8=mt_rand(0,31415926)/10000000;
// amplitudes
$rand9=mt_rand(330,420)/110;
$rand10=mt_rand(330,450)/100;
//wave distortion
for($x=0;$x<$width;$x++){
for($y=0;$y<$height;$y++){
$sx=$x+(sin($x*$rand1+$rand5)+sin($y*$rand3+$rand6))*$rand9-$width/2+$center+1;
$sy=$y+(sin($x*$rand2+$rand7)+sin($y*$rand4+$rand8))*$rand10;
if($sx<0 || $sy<0 || $sx>=$width-1 || $sy>=$height-1){
continue;
}else{
$color=imagecolorat($img, $sx, $sy) & 0xFF;
$color_x=imagecolorat($img, $sx+1, $sy) & 0xFF;
$color_y=imagecolorat($img, $sx, $sy+1) & 0xFF;
$color_xy=imagecolorat($img, $sx+1, $sy+1) & 0xFF;
}
if($color==255 && $color_x==255 && $color_y==255 && $color_xy==255){
continue;
}else if($color==0 && $color_x==0 && $color_y==0 && $color_xy==0){
$newred=$foreground_color[0];
$newgreen=$foreground_color[1];
$newblue=$foreground_color[2];
}else{
$frsx=$sx-floor($sx);
$frsy=$sy-floor($sy);
$frsx1=1-$frsx;
$frsy1=1-$frsy;
$newcolor=(
$color*$frsx1*$frsy1+
$color_x*$frsx*$frsy1+
$color_y*$frsx1*$frsy+
$color_xy*$frsx*$frsy
);
if($newcolor>255) $newcolor=255;
$newcolor=$newcolor/255;
$newcolor0=1-$newcolor;
$newred=$newcolor0*$foreground_color[0]+$newcolor*$background_color[0];
$newgreen=$newcolor0*$foreground_color[1]+$newcolor*$background_color[1];
$newblue=$newcolor0*$foreground_color[2]+$newcolor*$background_color[2];
}
imagesetpixel($img2, $x, $y, imagecolorallocate($img2, $newred, $newgreen, $newblue));
}
}
$this->showImage($img2);
}
public function getString(){
return $this->keystring;
}
private function randString($length){
$str = '';
$allowed_symbols = "23456789abcdegikpqsvxyz"; //without symbols (o=0, 1=l, i=j, t=f)
while(true){
$str = '';
for($i=0;$i<$length;$i++){
$num = mt_rand(0,strlen($allowed_symbols)-1);
$str .= $allowed_symbols[$num];
}
if(!preg_match('/cp|cb|ck|c6|c9|rn|rm|mm|co|do|cl|db|qp|qb|dp|ww/',$str)) break;
}
return $str;
}
private function frand(){
return mt_rand(0,9999)/10000;
}
private function drawLine(&$img,$width,$height){
$line_number = 5;
$color_from = 100;
for ($line = 0; $line < $line_number; ++ $line) {
$line_color = imagecolorallocate($img, mt_rand($color_from,255),
mt_rand($color_from, 255),mt_rand($color_from, 255));
$x = $width * (1 + $line) / ($line_number + 1);
$x += (0.5 - $this->frand()) * $width / $line_number;
$y = mt_rand($height * 0.1, $height * 0.9);
$theta = ($this->frand() - 0.5) * M_PI * 0.7;
$w = $width;
$len = mt_rand($w * 0.4, $w * 0.7);
$lwid = mt_rand(0, 2);
$k = $this->frand() * 0.6 + 0.2;
$k = $k * $k * 0.5;
$phi = $this->frand() * 6.28;
$step = 0.5;
$dx = $step * cos($theta);
$dy = $step * sin($theta);
$n = $len / $step;
$amp = 1.5 * $this->frand() / ($k + 5.0 / $len);
$x0 = $x - 0.5 * $len * cos($theta);
$y0 = $y - 0.5 * $len * sin($theta);
$ldx = round(- $dy * $lwid);
$ldy = round($dx * $lwid);
for ($i = 0; $i < $n; ++ $i) {
$x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
$y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
imagefilledrectangle($img, $x, $y, $x + $lwid, $y + $lwid,$line_color);
}
}
$allowed_symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
for ($i = 0; $i < 20; $i++) {//写入随机字串
$char = $allowed_symbols[mt_rand(0,strlen($allowed_symbols)-1)];
$line_color = imagecolorallocate($img,
mt_rand($color_from,255),mt_rand($color_from, 255),mt_rand($color_from, 255));
imagechar($img,mt_rand(0,4),mt_rand(0,$width),rand(0,$height),$char,$line_color);
}
}
private function showImage(&$img){
ob_get_clean();
$out = ob_get_clean();//清除之前所有输出缓冲 TODO
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');
if(function_exists("imagejpeg")){
header("Content-Type: image/jpeg");
imagejpeg($img, null,90);//图片质量
}else if(function_exists("imagegif")){
header("Content-Type: image/gif");
imagegif($img);
}else if(function_exists("imagepng")){
header("Content-Type: image/x-png");
imagepng($img);
}
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/Pinyin.class.php'
<?php
/**
* 将中文编码成拼音;
*
* 纯utf8字库方式;其他方案:utf-8转为gbk,gbk中文是按拼音索引的
* 多音字处理[根据上下文词语自动识别; 未在词库中则使用默认(高频的部分省略词库,作为默认拼音)]
*
* Pinyin::get($str,$format=[all|first],$add='');[all|first] 全部拼音|首字母
*/
class Pinyin{
public static function get($str,$format='',$add='',$addAll=''){
static $map = null;
static $mapPoly = null;
$format = $format ? $format : 'all';
$strArr = self::split($str);
$result = '';$len = count($strArr);
$isFirst = $format === 'first';
$chineseIndex = 0;
for($index = 0;$index < $len;$index++){
$char = $strArr[$index];
if(strlen($char) == 1){
$chineseIndex = 0;
$result .= $char;continue;
}
if(!$map){$map = self::map();$mapPoly = self::mapPoly();}
$pinyin = $map[$char];$chineseIndex++;
$addStr = ($chineseIndex == 1)? $addAll.$add :$add;
if(!$pinyin){$result .= $char;continue;}
if(!$mapPoly[$char]){$result .= ($isFirst ? $pinyin[0]:$addStr.$pinyin);continue;}
$charNode = $mapPoly[$char];$mapChar = $charNode[1];
$findWords = $index > 0 ? $mapChar[$strArr[$index-1]]:false; //通过左右相邻字初步筛选;
$findWords = $findWords ? $findWords : $mapChar[$strArr[$index+1]];
if(!$findWords){
$pinyin = $charNode[0];
}else if(count($findWords) == 1 && $findWords[0][1] == 2){
$pinyin = $findWords[0][0];
}else{
$pinyin = $charNode[0];
foreach($findWords as $item){
$strPick = array_slice($strArr,$index - $item[2],$item[1]);
if(implode('',$item[3]) === implode('',$strPick)){
$pinyin = $item[0];break;
}
}
}
$result .= ($isFirst ? $pinyin[0]:$addStr.$pinyin);
}
return $result ? $result:'';
}
public static function encode($str,$format='all',$add=''){
return self::get($str,$format,$add);
}
public static function split($str){
return preg_split("//u",$str,-1,PREG_SPLIT_NO_EMPTY);
}
// 多音字词库; 无声无臭;无臭味;
public static function mapPoly(){
// "落":"luo;lao:落枕,落价;la:落下,出落"
// "落":['luo',{"枕":[['lao',2,0,"落枕",","], ], ...}]
$rows = array(
"阿"=>"a;e:依阿取容,太阿倒持,守正不阿,公正不阿,刚直不阿,刚正不阿,奉公不阿,方正不阿,法不阿贵,倒持泰阿,柴立不阿,阿谀取容,阿谀奉承,阿谀逢迎,阿谀谄媚,阿意取容,阿世媚俗,阿世取容,阿世盗名,阿时趋俗,阿其所好,阿弥陀佛,阿党相为,阿党比周,阿房宫,东阿,阿胶",
"弟"=>"di;ti:入孝出弟,岂弟君子",
"矜"=>"jin;guan:孤独矜寡",
"乐"=>"le;yue:靡靡之乐,礼坏乐崩,礼崩乐坏,钧天广乐,摇滚乐,爵士乐,交响乐,作乐,奏乐,音乐,雅乐,弦乐,西乐,声乐,配乐,民乐,礼乐,乐章,乐音,乐舞,乐团,乐坛,乐师,乐曲,乐器,乐谱,乐迷,乐律,乐户,乐官,乐工,乐歌,乐感,乐府,乐队,乐池,军乐,管乐,鼓乐,哀乐;yao:乐山乐水",
"思"=>"si;sai:于思",
"称"=>"cheng;chen:铢两悉称,能不称官,侔色揣称,称体载衣,称体裁衣,称家有无,匀称,相称,配称,对称,称职,称愿,称心,称身",
"巷"=>"xiang;hang:巷道,平巷;xiong:柳巷花街,柳街花巷",
"难"=>"nan;cai:人才难得",
"度"=>"du;duo:铢量寸度,昼度夜思,以己度人,审时度势,审己度人,量力度德,揆情度理,揆理度情,鉴影度形,度己以绳,度德量力,揣时度力,称德度功,不可揆度,臆度,审度,窥度,忖度,揣度,测度,裁度,猜度",
"分"=>"fen;fan:别类分门",
"脉"=>"mai;mo:脉脉",
"摩"=>"mo;ma:摩挲",
"期"=>"qi;ji:期年",
"说"=>"shuo;shui:说项,说客,说服;liang:打开天窗说亮话;yue:和颜说色",
"藏"=>"cang;zang:青藏高原,藏红花,西藏,三藏,道藏,大藏,藏族,藏戏,藏青,藏历,藏蓝,宝藏;she:用行舍藏",
"合"=>"he;ge:朝升暮合",
"转"=>"zhuan;zhuai:转文",
"拗"=>"niu;ao:违拗,拗口,拗断",
"秘"=>"mi;bi:秘鲁",
"角"=>"jiao;jue:以宫笑角,埒才角妙,坤角儿,豆角儿,主角,生角,配角,名角,口角,角逐,角色,角力,角斗,旦角,丑角",
"邪"=>"xie;ye:莫邪",
"扒"=>"ba;pa:吃里扒外,扒耳搔腮,扒手,扒窃,扒灰,扒糕",
"车"=>"che;ju:丢卒保车",
"嗒"=>"da;ta:嗒然,嗒丧",
"干"=>"gan;qian:旋干转坤,涸思干虑,河涸海干,白干",
"露"=>"lu;lou:暴露文学,露一手,露马脚,泄露,露相,露馅,露怯,露苗,露面,露脸,露骨,露富,露风,露底,露丑,露白",
"区"=>"qu;ou:老区",
"食"=>"shi;si:箪食瓢饮,箪食壶酒,箪食壶浆",
"蛇"=>"she;yi:委蛇",
"术"=>"shu;zhu:苍术,白术",
"汤"=>"tang;shang:浩浩汤汤,沸沸汤汤,峨峨汤汤",
"条"=>"tiao;di:条畅",
"相"=>"xiang;xieng:虮虱相吊;xing:枝叶相持",
"血"=>"xue;xie:一针见血,刀刀见血,血淋淋,血糊糊,洒狗血,鸡血石,血晕,吐血,咯血,流血",
"会"=>"hui;kuai:头会箕赋,会计,财会",
"叶"=>"ye;xie:叶韵",
"柏"=>"bai;bo:柏拉图,柏林;bia:餐松啖柏",
"弄"=>"nong;long:弄堂,弄口,里弄",
"坏"=>"huai;pi:凿坏以遁,凿坏而遁",
"将"=>"jiang;qiang:将伯之助,将伯之呼,将将,将进酒",
"落"=>"luo;lao:莲花落,落子,落枕,落价;la:丢三落四,落下,出落",
"亡"=>"wang;ben:追亡逐北",
"读"=>"du;dou:句读;shu:囊萤照读",
"佛"=>"fo;fu:仿佛",
"见"=>"jian;xian:图穷匕首见,图穷匕见,尸居龙见,情见势屈,情见力屈,情见乎辞,见素抱朴,间见层出,见世面,互见",
"禅"=>"chan;shan:封禅,禅让",
"长"=>"chang;zhang:此风不可长,莺飞草长,土生土长,停留长智,水长船高,女长须嫁,女长当嫁,目无尊长,阑风长雨,教学相长,渐不可长,根生土长,辅世长民,长幼尊卑,长幼有叙,长幼有序,长年三老,长虺成蛇,长傲饰非,草长莺飞,傲不可长,敖不可长,司务长,灵长目,列车长,护士长,参谋长,百夫长,总长,茁长,助长,州长,站长,增长,学长,兄长,校长,消长,县长,外长,团长,徒长,庭长,首长,市长,师长,生长,酋长,排长,年长,科长,军长,见长,家长,机长,官长,股长,队长,村长,次长,成长,厂长,长子,长者,长兄,长相,长物,长孙,长势,长上,长亲,长吏,长老,长进,长官,长房,长大,长膘,长辈,部长,班长",
"差"=>"cha;chai:神差鬼使,鬼使神差,开小差,专差,抓差,支差,邮差,信差,听差,钦差,美差,苦差,解差,交差,兼差,官差,公差,跟差,当差,出差,撤差,差役,差事,差遣,差使,兵差,办差;ci:栉比鳞差,参差",
"大"=>"da;tai:大璞不完,大子;dai:大夫",
"数"=>"shu;shuo:数见不鲜,多言数穷,频数",
"载"=>"zai;cai:称体载衣",
"和"=>"he;huo:画荻和丸,趁水和泥,和稀泥,软和,热和,暖和,搅和,和弄,和面,搀和,掺和,拌和",
"扎"=>"zha;za:扎染,结扎,包扎",
"臂"=>"bi;bei:胳臂",
"磅"=>"pang;bang:过磅,地磅,磅秤",
"被"=>"bei;pi:青紫被体,被山带河,被甲执兵,被甲枕戈,被甲据鞍,被甲持兵,被褐怀珠,被褐怀玉,被发左衽,被发缨冠,被发文身",
"括"=>"kuo;gua:挺括,搜括",
"络"=>"luo;lao:络子",
"刹"=>"sha;cha:刹那,罗刹,古刹,梵刹,宝刹",
"石"=>"shi;dan:以升量石,悬石程书",
"单"=>"dan;shan:单姓;chan:单于",
"有"=>"you;fu:左宜右有",
"重"=>"zhong;chong:救寒莫如重裘,坐不重席,重足一迹,重足屏息,重足屏气,重足累息,重足而立,重纸累札,重整旗鼓,重振旗鼓,重垣叠锁,重垣迭锁,重裀列鼎,重岩叠嶂,重岩迭障,重兴旗鼓,重熙累叶,重熙累盛,重熙累洽,重熙累绩,重手累足,重生爷娘,重生父母,重山峻岭,重山复水,重山复岭,重三叠四,重三迭四,重起炉灶,重纰貤缪,重葩累藻,重明继焰,重门击柝,重峦复嶂,重峦叠嶂,重峦叠巘,重峦迭嶂,重峦迭巘,重理旧业,重金袭汤,重金兼紫,重见天日,重迹屏气,重珪叠组,重珪迭组,重规袭矩,重规叠矩,重规累矩,重规迭矩,重规沓矩,重圭叠组,重关击柝,重铬酸钾,重睹天日,重蹈覆辙,重床叠屋,重床叠架,重床迭屋,重床迭架,重操旧业,一重一掩,双足重茧,手足重茧,食不重味,累屋重架,老调重谈,卷土重来,居不重茵,居不重席,旧地重游,昏镜重磨,昏镜重明,规重矩叠,方寸万重,豆重榆瞑,叠矩重规,迭矩重规,沉谋重虑,百舍重趼,百舍重茧,重奏,重重,重圆,重映,重影,重印,重译,重洋,重阳,重演,重修,重行,重新,重霄,重现,重温,重围,重头,重孙,重提,重数,重述,重审,重申,重庆,重拍,重聚,重九,重建,重婚,重合,重光,重复,重逢,重犯,重返,重叠,重弹,重出,重唱,重播,重版,双重,三重,二重",
"堡"=>"bao;pu:大堡礁,土堡,地堡;bu:堡子",
"信"=>"xin;shen:卬首信眉",
"知"=>"zhi;shi:释知遗形",
"暴"=>"bao;pu:一暴十寒,暴衣露冠,暴衣露盖,暴腮龙门",
"行"=>"xing;hang:行行出状元,一目五行,一目数行,寻行数墨,秀出班行,行行蛇蚓,随行就市,泣数行下,欺行霸市,各行各业,当行出色,大行大市,搀行夺市,太行山,大行星,十行,九行,八行,七行,六行,四行,二行,银行,转行,在行,洋行,雁行,行业,行伍,行市,行商,行情,行列,行距,行间,行家,行货,行会,行话,行号,行规,行道,行当,行辈,行帮,外行,同行,跳行,时行,诗行,商行,三行,戎行,农行,内行,粮行,隔行,改行,分行,懂行,成行,本行;heng:道行",
"卒"=>"zu;cu:仓卒",
"陂"=>"bei;po:陂陀",
"咽"=>"yan;ye:幽咽,呜咽,哽咽,抽咽",
"拓"=>"tuo;ta:拓印,拓片,拓本",
"朝"=>"zhao;chao:枵腹终朝,身先朝露,三朝元老,三朝五日,人生朝露,暮想朝思,暮四朝三,暮去朝来,暮鼓朝钟,暮翠朝红,暮爨朝舂,暮楚朝秦,流水朝宗,九间朝殿,江汉朝宗,改朝换姓,改朝换代,匪朝伊夕,返本朝元,断烂朝报,东市朝衣,得胜回朝,丹凤朝阳,朝章国故,朝章国典,朝阳丹凤,朝成暮徧,不讳之朝,班师回朝,百鸟朝凤,百川朝海,朝鲜族,朝堂,朝中,朝里,早朝,在朝,元朝,王朝,退朝,天朝,宋朝,胜朝,上朝,前朝,南朝,明朝,面朝,六朝,临朝,历朝,皇朝,当朝,朝着,朝政,朝野,朝向,朝廷,朝天,朝圣,朝上,朝日,朝觐,朝见,朝贡,朝纲,朝服,朝臣,朝代,朝拜,北朝",
"齐"=>"qi;ji:时运不齐",
"壳"=>"ke;qiao:金蝉脱壳,躯壳,甲壳,地壳",
"景"=>"jing;ying:灭景追风,急景凋年,顾景惭形",
"率"=>"lv;shuai:正身率下,整躬率物,适情率意,率由旧章,率由旧则,率以为常,率兽食人,率马以骥,率尔成章,率尔操觚,百兽率舞,率土,直率,真率,相率,统率,坦率,轻率,率直,率真,率性,率然,率领,督率,大率,草率,表率",
"贲"=>"ben;bi:贲临",
"着"=>"zhe;zhao:八竿子打不着,着三不着两,走为上着,知疼着痒,知疼着热,歪打正着,棋输先着,棋高一着,摸头不着,摸门不着,百下百着,支着儿,这么着,怎么着,阴着儿,说不着,数得着,数不着,那么着,摸不着,干着急,犯得着,犯不着,着数,着迷,着凉,失着,该着,点着;zhuo:着手成春,着人先鞭,枝附叶着,先我着鞭,魂不着体,佛头着粪,当着不着,大处着眼,大处着墨,穿红着绿,吃着不尽,不着疼热,鞭辟着里,着重号,着眼点,软着陆,着意,着边,执着,衣着,吸着,无着,固着,附着,沉着;zhu:着书立说,彰明较着,以微知着,仰屋着书",
"伯"=>"bo;bai:大伯子",
"解"=>"jie;xie:跑马卖解,解数,解法",
"射"=>"she;ye:姑射神人,射干",
"迫"=>"po;pai:迫击炮",
"塞"=>"sai;se:昭德塞违,抑塞磊落,茅塞顿开,荆棘塞途,晦盲否塞,顿开茅塞,蔽明塞聪,蔽聪塞明,闭目塞听,闭目塞耳,闭明塞聪,闭门塞户,闭门塞窦,拔本塞源,拔本塞原,挨山塞海,阻塞,语塞,淤塞,壅塞,拥塞,搪塞,栓塞,塞责,塞音,梗塞,哽塞,堵塞,充塞,闭塞",
"咯"=>"ge;ka:咯血",
"调"=>"diao;tiao:左支右调,众口难调,雨顺风调,瑟弄琴调,瑟调琴弄,饶舌调唇,琴瑟不调,品竹调丝,蜜里调油,胶柱调瑟,风调雨顺,调嘴学舌,调嘴弄舌,调朱弄粉,调朱傅粉,调嘴调舌,调脂弄粉,调丝品竹,调神畅情,调舌弄唇,调三斡四,调三惑四,调三窝四,调墨弄笔,调良稳泛,调风弄月,调风变俗,调词架讼,调唇弄舌,协调,失调,烹调,空调,解调,调资,调准,调治,调制,调整,调匀,调养,调音,调谑,调谐,调协,调笑,调戏,调息,调味,调停,调唆,调适,调试,调摄,调色,调情,调频,调皮,调弄,调料,调理,调侃,调控,调解,调节,调教,调价,调焦,调剂,调级,调护,调和,调合,调光,调羹,调幅,调调,调档,调处,调拨",
"削"=>"xue;xiao:削皮,切削,尖削,刮削,刀削,车削",
"薄"=>"bo;bao:高义薄云天,西山日薄,帏薄不修,势孤力薄,身微力薄,日薄桑榆,日薄虞渊,轻繇薄赋,轻徭薄税,轻徭薄赋,轻傜薄赋,轻口薄舌,轻赋薄敛,轻薄无知,轻薄无行,轻薄无礼,命薄缘悭,门衰祚薄,厚往薄来,官情纸薄,寡情薄意,根孤伎薄,雕虫薄技,德浅行薄,德薄才鲜,道微德薄,薄情无义,薄唇轻言,瘠薄,厚薄,薄葬,薄纱,薄膜,薄片,薄面,薄脆,薄层,薄薄,薄饼,薄板;bu:对薄公堂",
"得"=>"de;dei:总得,非得,必得",
"剥"=>"bo;bao:敲骨剥髓,活剥生吞,抽丝剥茧,剥脱,剥皮,剥取,剥壳,剥剥,剥除,毕剥",
"裨"=>"bi;pi:裨将",
"辟"=>"pi;bi:不辟斧钺,鞭辟着里,鞭辟向里,复辟,辟邪,辟谷",
"绿"=>"lv;lu:绿林强盗,绿林豪客,绿林豪士,绿林好汉,绿林豪杰,绿林大盗,鸭绿江",
"还"=>"huan;hai:还没,还须,还需,摊还,还政,还田,还是,还好,抵还",
"卡"=>"ka;qia:卡脖子,税卡,哨卡,路卡,卡子,卡壳,卡具,关卡,发卡,边卡",
"内"=>"nei;na:深文周内,鸡内金",
"校"=>"xiao;jiao:校短量长,犯而不校,校准,校注,校正,校阅,校样,校验,校勘,校核,校改,校对,校订,校点,校场,审校,勘校,参校",
"著"=>"zhu;zhuo:枝附叶著,一鞭先著,头上著头,水中著盐,视微知著,识微知著,棋输先著,魂不著体,画蛇著足,佛头著粪,执著",
"扁"=>"bian;pian:扁舟",
"便"=>"bian;pian:空腹便便,大腹便便,便宜",
"了"=>"liao;le:跑了和尚跑不了寺,跑了和尚跑不了庙,一块石头落了地,赔了夫人又折兵,好心做了驴肝肺,好了疮疤忘了痛,拔了萝卜地皮宽,无了无休,无了根蒂,凉了半截,铁了心,好极了,为了,完了,算了,临了,到了,除了",
"溺"=>"ni;niao:屙金溺银,便溺",
"识"=>"shi;zhi:博闻强识,款识,附识",
"尺"=>"chi;che:工尺",
"的"=>"de;di:众矢之的,有的放矢,移的就箭,一语中的,一语破的,无的放矢,的一确二,冰解的破,可的松,阿的平,目的,的士,的确,的当,标的",
"亲"=>"qin;qing:亲家",
"徵"=>"zhi;zheng:含商咀徵,含宫咀徵",
"传"=>"chuan;zhuan:投传而去,树碑立传,圣经贤传,自传,正传,小传,外传,评传,内传,列传,经传,传略,传记,别传",
"提"=>"ti;di:提溜,提防",
"从"=>"cong;zong:合从连衡",
"槟"=>"bin;bing:槟榔",
"纶"=>"lun;guan:纶巾",
"铛"=>"dang;cheng:鼎铛有耳,鼎铛玉石,饼铛",
"给"=>"gei;ji:饔飧不给,日不暇给,人足家给,人给家足,目不暇给,家给人足,家给民足,呼不给吸,自给,仰给,配给,进给,供给,给予,给养,给水,补给",
"折"=>"zhe;she:折腰五斗,折箭为誓,月中折桂,推枯折腐,深文曲折,曲曲折折,强自取折,千磨百折,攀花折柳,攀蟾折桂,面折庭争,面折廷诤,拉枯折朽,将功折过,桂折一枝,桂折兰摧,规旋矩折,浮收勒折,栋折榱坏,东量西折,鼎折餗覆,鼎折覆餗,得马折足,榱栋崩折,榱崩栋折,朝折暮折,朝攀暮折,折衷,折损,折辱,折耗,折堕,折秤,折本,屈折",
"颈"=>"jing;geng:脖颈",
"泊"=>"bo;po:血泊,湖泊,泊地",
"擘"=>"bo;bai:金翅擘海",
"卜"=>"bu;bo:握粟出卜,萝卜",
"不"=>"bu;fou:以不济可",
"觉"=>"jue;jiao:一觉,午觉,睡觉,困觉",
"曾"=>"zeng;ceng:曾无与二,曾几何时,得未曾有,曾经,似曾,不曾",
"属"=>"shu;zhu:属垣有耳,属毛离里,属辞比事,属词比事,波属云委,波骇云属,比物属事",
"择"=>"ze;zhai:择席,择菜",
"参"=>"can;shen:曾参杀人,月没参横,月落参横,日月参辰,扪参历井,斗转参横,参横斗转,参回斗转,参辰卯酉,参辰日月,西洋参,高丽参,沙参,人参,苦参,海参,党参,丹参,参商;cen:参伍错综,参错,参差",
"沙"=>"sha;she:飞沙走砾",
"颉"=>"jie;xie:颉颃",
"伧"=>"cang;chen:寒伧",
"劲"=>"jin;jing:贞松劲柏,清风劲节,强弓劲弩,陵劲淬砺,高风劲节,死劲儿,雄劲,遒劲,强劲,劲直,劲射,劲旅,劲风,劲敌,劲吹,劲草,刚劲,苍劲",
"芥"=>"jie;gai:芥蓝",
"泽"=>"ze;shi:振兵泽旅",
"屏"=>"ping;bing:屏声息气,屏息,屏退,屏弃,屏气,屏除",
"匙"=>"chi;shi:钥匙",
"颤"=>"chan;zhan:冷颤,寒颤,打颤,颤栗",
"盛"=>"sheng;cheng:盛水不漏",
"没"=>"mei;mo:月没参横,头没杯案,头出头没,神出鬼没,没衷一是,没没无闻,没金饮羽,赍志而没,击排冒没,没奈何,湮没,淹没,吞没,辱没,泯没,没药,没收,没世,没入,没落,没齿,埋没,沦没,浸没,籍没,汩没,覆没,出没,沉没",
"嘲"=>"chao;zhao:嘲哳",
"红"=>"hong;gong:女红",
"尾"=>"wei;yi:马尾",
"都"=>"du;dou:一身都是胆,吁咈都俞,研京练都,通邑大都,通都巨邑,通都大埠,三徙成都,清都紫微,清都紫府,清都绛阙,冥漠之都,鸿都买第,洪都拉斯,都俞吁咈,长鸣都尉,都柏林,昌都县,中都,全都,乐都,都会",
"朴"=>"pu;piao:姓朴;po:朴硝,厚朴",
"澄"=>"cheng;deng:红澄澄,澄沙",
"强"=>"qiang;jiang:倔头强脑,外强,强嘴,倔强",
"缩"=>"suo;su:缩砂密",
"缪"=>"miu;mou:绸缪",
"恶"=>"e;wu:众好众恶,以大恶细,痛深恶绝,同恶相助,同恶相恤,深恶痛疾,深恶痛绝,深恶痛嫉,善善恶恶,好逸恶劳,好佚恶劳,好善恶恶,恶紫夺朱,恶醉强酒,恶湿居下,恶居下流,恶恶从短,恶不去善,爱生恶死,憎恶,厌恶,羞恶,嫌恶,痛恶,可恶,交恶,好恶;er:鬼怕恶人;le:溢美溢恶",
"臭"=>"chou;xiu:无声无臭,无伤无臭,臭味相投,乳臭",
"奇"=>"qi;ji:飞将数奇,奇函数,奇数,奇偶,奇零",
"圈"=>"quan;juan:圈牢养物,羊圈,畜圈,棚圈,马圈,垫圈",
"弹"=>"dan;tan:以珠弹雀,一弹指顷,随珠弹雀,隋珠弹雀,品竹弹丝,明珠弹雀,击石弹丝,古调单弹,古调不弹,弹指之间,弹丸脱手,弹丝品竹,弹空说嘴,弹斤估两,弹剑作歌,吹拉弹唱,弹吉他,弹冠,轻弹,弹琴,重弹,评弹,抨弹,乱弹,回弹,弹性,弹射,弹词,吹弹",
"呲"=>"zi;ci:白不呲咧",
"浅"=>"qian;jian:浅浅",
"撮"=>"cuo;zuo:一撮",
"夯"=>"hang;ben:心拙口夯",
"嚼"=>"jiao;jue:嚼墨喷纸,咀嚼,大嚼",
"系"=>"xi;ji:悬龟系鱼,红绳系足,赤绳系足,长绳系日,系铃,系绳,系带,系泊",
"澹"=>"dan;tan:澹台",
"叨"=>"dao;tao:叨在知己,叨陪末座,叨扰,叨光",
"椎"=>"chui;zhui:椎髻布衣,悬鼓待椎,十夫楺椎,十夫桡椎,顿足椎胸,大路椎轮,大辂椎轮,腰椎,胸椎,脊椎,骶椎",
"核"=>"he;hu:核儿",
"降"=>"jiang;xiang:一物降一物,降妖捉怪,降龙伏虎,拱手而降,伏虎降龙,招降,诈降,诱降,投降,受降,劝降,求降,请降,乞降,纳降,降伏,归降",
"琢"=>"zhuo;zuo:琢磨",
"摄"=>"she;nie:追风摄景",
"耙"=>"pa;ba:钉齿耙,耥耙,耙地",
"侗"=>"dong;tong:倥侗",
"吓"=>"xia;he:威吓,恐吓,恫吓",
"模"=>"mo;mu:装模作样,一模一样,人模狗样,字模,木模,模子,模样,模具,模板,锻模",
"敦"=>"dun;dui:朱槃玉敦,朱盘玉敦",
"么"=>"me;yao:挑么挑六",
"咱"=>"zan;za:咱家,多咱",
"堕"=>"duo;hui:百堕俱举",
"尿"=>"niao;sui:尿泡,尿脬",
"娜"=>"nuo;na:雅典娜",
"番"=>"fan;pan:番禺",
"殖"=>"zhi;shi:骨殖",
"省"=>"sheng;xing:昏定晨省,晨昏定省,不省,日省,三省,自省,省悟,省视,省亲,省察,深省,内省,归省,反省",
"泌"=>"mi;bi:泌阳",
"泥"=>"ni;nie:泥而不滓",
"爪"=>"zhao;zhua:爪尖儿,爪子,爪儿",
"否"=>"fou;pi:泰来否往,泰极而否,晦盲否塞,否终则泰,否终复泰,否往泰来,否去泰来,否极阳回,否极泰来,否极泰回,臧否",
"贾"=>"jia;gu:余勇可贾,炫玉贾石,南贩北贾,多钱善贾,多财善贾,行贾,巨贾,贾人,贾祸",
"伽"=>"jia;qie:伽蓝;ga:伽马射线",
"吱"=>"zhi;zi:吱扭",
"咳"=>"ke;hai:咳声叹气,百日咳,咳咳",
"蛤"=>"ha;ge:雕蚶镂蛤,文蛤,蛤蜊,蛤蚧,蛤粉",
"宿"=>"su;xiu:宿雨餐风,宿水飡风,宿水餐风,硕望宿德,水宿山行,水宿风餐,霜行草宿,深仇宿怨,山行海宿,栖风宿雨,老师宿儒,二十八宿,一宿,星宿",
"栅"=>"zha;shan:栅极,水栅,木栅,栏栅,光栅",
"畜"=>"chu;xu:养精畜锐,仰事俯畜,畜妻养子,畜养,畜牧,畜产",
"券"=>"quan;xuan:拱券",
"偻"=>"lou;lv:指不胜偻,伛偻",
"堑"=>"qian;pian:颓垣断堑",
"枸"=>"gou;ju:枸橼",
"碌"=>"lu;liu:碌碡",
"蔓"=>"man;wan:抱蔓摘瓜,枝蔓,藤蔓,瓜蔓",
"呱"=>"gua;gu:呱呱",
"纤"=>"xian;qian:扯纤拉烟,纤绳,纤手,纤夫,拉纤",
"龟"=>"gui;jun:龟裂",
"挟"=>"xie;jia:挟主行令,挟势弄权",
"似"=>"si;shi:似的",
"蚌"=>"bang;beng:蚌埠市",
"貉"=>"he;hao:貉绒",
"铅"=>"qian;yan:铅山",
"苕"=>"shao;tiao:苕帚",
"吁"=>"xu;yu:吁天呼地,吁咈都俞,呼天吁地,吁求,吁请,呼吁",
"呢"=>"ni;ne:制服呢,线呢",
"稽"=>"ji;qi:稽首",
"伺"=>"si;ci:伺候",
"雀"=>"que;qiao:雀子,家雀",
"剿"=>"jiao;chao:剿袭",
"埋"=>"mai;man:埋天怨地,埋三怨四,埋怨",
"攒"=>"cuan;zan:攒眉苦脸,百虑攒心,攒竹,攒攒,攒钱,积攒",
"缉"=>"ji;qi:捱风缉缝",
"什"=>"shi;shen:什么",
"犍"=>"jian;qian:犍为",
"徼"=>"jiao;yao:离本徼末",
"揭"=>"jie;qi:深厉浅揭",
"藉"=>"jie;ji:人言藉藉,饿殍枕藉,狼藉",
"靓"=>"liang;jing:靓妆",
"仔"=>"zi;zai:歌仔戏,打工仔,牛仔,马仔,靓仔",
"桔"=>"jie;ju:橙黄桔绿",
"隽"=>"jun;juan:隽永",
"噱"=>"xue;jue:可发一噱",
"咖"=>"ka;ga:咖喱",
"扛"=>"gang;kang:扛长工,扛起,扛活",
"吭"=>"keng;hang:引吭高声,引吭高歌,引吭高唱,引吭悲歌,批吭捣虚,捣虚批吭;gang:扼吭拊背,扼吭夺食",
"腊"=>"la;xi:厚味腊毒",
"莨"=>"liang;lang:莨菪",
"潦"=>"liao;lao:潦原浸天",
"烙"=>"lao;luo:炮烙",
"趄"=>"ju;qie:趔趄",
"氓"=>"mang;meng:愚氓,群氓",
"粥"=>"zhou;yu:群雌粥粥",
"槛"=>"jian;kan:雕楹碧槛,门槛",
"糜"=>"mi;mei:积谗糜骨,糜子",
"黾"=>"min;meng:黾穴鸲巢",
"抹"=>"mo;ma:抹脸,抹布",
"莫"=>"mo;mu:岁聿其莫",
"牟"=>"mou;mu:释迦牟尼",
"哪"=>"na;nei:哪会儿,哪些,哪个;ne:哪吒",
"那"=>"na;nei:那些",
"裳"=>"shang;chang:裂裳裹足,掎裳连袂,毁冠裂裳,颠倒衣裳,倒裳索领,霓裳",
"疟"=>"nve;yao:疟子",
"刨"=>"pao;bao:刨子,刨刀,刨床,刨冰",
"睥"=>"bi;pi:睥睨一切",
"曝"=>"pu;bao:曝光",
"耆"=>"qi;shi:追趋逐耆",
"岂"=>"qi;kai:岂弟君子",
"氏"=>"shi;zhi:月氏",
"膻"=>"shan;dan:膻中",
"沈"=>"shen;chen:沈博绝丽",
"螫"=>"shi;zhe:蝎蝎螫螫",
"钥"=>"yao;yue:北门管钥,抱关执钥,锁钥",
"倘"=>"tang;chang:倘佯",
"褪"=>"tui;tun:褪去",
"苣"=>"ju;qu:苣荬菜",
"喔"=>"wo;o:喔唷",
"腌"=>"yan;a:腌臜",
"芫"=>"yuan;yan:芫荽",
"殷"=>"yin;yan:殷红",
"柚"=>"zhou;you:柚木",
"咋"=>"ze;zha:咋呼;za:鼓唇咋舌",
"这"=>"zhe;zhei:这些",
"圜"=>"huan;yuan:破觚为圜",
"疐"=>"zhi;zu:进退跋疐;shu:流离颠疐;mao:前跋后疐",
"冯"=>"feng;ping:暴虎冯河",
"絜"=>"xie;jie:渊清玉絜,材茂行絜",
"匮"=>"kui;gui:石室金匮,金匮石室",
"喳"=>"zha;cha:嘁哩喀喳,啛啛喳喳",
"莩"=>"piao;fu:葭莩之亲",
"擿"=>"ti;zhai:擿植索涂,擿埴索涂,擿埴索途;zhi:冥行擿埴",
"尨"=>"meng;mang:尨眉皓发",
"吷"=>"gui;xue:剑头一吷",
"泆"=>"yi;die:泆荡",
"燋"=>"jiao;zhuo:鱼游燋釜",
"籓"=>"zu;fan:飘籓坠溷",
"麇"=>"jun;qun:麇至沓来",
"儗"=>"li;ni:儗非其伦",
"埶"=>"yi;shi:神龙失埶,审曲面埶,情见埶竭",
"铤"=>"ting;ding:铤鹿走险",
"亹"=>"wei;men:亹源"
);
$map = array();
foreach($rows as $char=>$row) {
$rowArr = explode(';',$row);
$mapChar = array();
if(!$rowArr[0]){continue;}
foreach ($rowArr as $i=>$words){
if($i == 0) continue;
$wordsArr = explode(':',$words);//lao:落枕,落价
if(count($wordsArr) != 2) continue;
$wordsValueArr = explode(',',$wordsArr[1]);
foreach($wordsValueArr as $word){
if(!$word) continue;
$strArr = self::split($word);
$indexAt = array_search($char,$strArr);
$charNear= $indexAt == 0 ? $strArr[1]:$strArr[$indexAt - 1];//右侧或左侧;
if(!$mapChar[$charNear]){$mapChar[$charNear] = array();}
$mapChar[$charNear][] = array($wordsArr[0],count($strArr),$indexAt,$strArr,$word);
}
}
$map[$char] = array($rowArr[0],$mapChar);
}
return $map;
}
// 汉字拼音数据;
public static function map(){
$data = 'yi:一,乁,乂,义,乙,亄,亦,亿,仡,以,仪,伇,伊,伿,佁,佚,佾,侇,依,俋,倚,偯,儀,億,兿,冝,刈,劓,劮,勚,勩,匇,匜,医,吚,呓,呭,呹,咦,咿,唈,噫,囈,圛,圯,坄,垼,埶,埸,墿,壱,壹,夁,夷,奕,妷,姨,媐,嫕,嫛,嬄,嬑,嬟,宐,宜,宧,寱,寲,屹,峄,峓,崺,嶧,嶬,嶷,已,巸,帟,帠,幆,庡,廙,异,弈,弋,弌,弬,彛,彜,彝,彞,役,忆,忔,怈,怡,怿,恞,悒,悘,悥,意,憶,懌,懿,扅,扆,抑,挹,揖,撎,攺,敡,敼,斁,旑,旖,易,晹,暆,曀,曎,曵,杙,杝,枍,枻,柂,栘,栧,栺,桋,棭,椅,椬,椸,榏,槸,檍,檥,檹,欭,欹,歝,殔,殪,殹,毅,毉,沂,沶,泆,洢,浂,浥,浳,湙,溢,漪,潩,澺,瀷,炈,焲,熠,熤,熪,熼,燚,燡,燱,狋,猗,獈,玴,瑿,瓵,畩,異,疑,疫,痍,痬,瘗,瘞,瘱,癔,益,眙,瞖,矣,礒,祎,禕,秇,移,稦,穓,竩,笖,簃,籎,縊,繄,繶,繹,绎,缢,羛,羠,義,羿,翊,翌,翳,翼,耴,肄,肊,胰,膉,臆,舣,艗,艤,艺,芅,苅,苡,苢,荑,萓,萟,蓺,薏,藙,藝,蘙,虉,蚁,蛜,蛡,蛦,蜴,螔,螘,螠,蟻,衣,衤,衪,衵,袘,袣,裔,裛,褹,襼,觺,訲,訳,詍,詒,詣,誃,誼,謻,譩,譯,議,讉,讛,议,译,诒,诣,谊,豙,豛,豷,貖,貤,貽,贀,贻,跇,跠,軼,輢,轙,轶,辷,迆,迤,迻,逘,逸,遗,遺,邑,郼,酏,醫,醳,醷,釔,釴,鈘,鈠,鉯,銥,鎰,鏔,鐿,钇,铱,镒,镱,阣,陭,隿,霬,靾,頉,頤,頥,顊,顗,颐,飴,饐,饴,駅,驛,驿,骮,鮧,鮨,鯣,鳦,鶂,鶃,鶍,鷁,鷊,鷖,鷧,鷾,鸃,鹝,鹢,鹥,黓,黟,黳,齮,齸,㐹,㑊,㑜,㑥,㓷,㔴,㕥,㖂,㘁,㘈,㘊,㘦,㙠,㙯,㚤,㚦,㛕,㜋,㜒,㝖,㞔,㠯,㡫,㡼,㢞,㣂,㣻,㥴,㦉,㦤,㦾,㩘,㫊,㰘,㰝,㰻,㱅,㱲,㲼,㳑,㴁,㴒,㵝,㵩,㶠,㹓,㹭,㺿,㽈,䄁,䄬,䄿,䆿,䇩,䇵,䉨,䋚,䋵,䌻,䎈,䐅,䐖,䓃,䓈,䓹,䔬,䕍,䖁,䖊,䗑,䗟,䗷,䘝,䘸,䝘,䝝,䝯,䞅,䢃,䣧,䦴,䧧,䩟,䬁,䬥,䬮,䭂,䭇,䭞,䭿,䮊,䯆,䰙,䱌,䱒,䲑,䴊,䴬|ding:丁,仃,叮,啶,奵,定,嵿,帄,忊,椗,玎,甼,疔,盯,矴,碇,碠,磸,耵,聢,聣,腚,萣,薡,訂,订,酊,釘,錠,鐤,钉,锭,靪,頂,顁,顶,飣,饤,鼎,鼑,㝎,㫀,㴿,㼗|kao:丂,尻,拷,攷,栲,洘,烤,犒,考,銬,铐,靠,髛,鮳,鯌,鲓,䐧,䯪|qi:七,乞,亓,亝,企,倛,僛,其,凄,剘,启,呇,呮,咠,唘,唭,啓,啔,啟,嘁,噐,器,圻,埼,夡,奇,契,妻,娸,婍,屺,岂,岐,岓,崎,嵜,帺,弃,忯,恓,悽,愒,愭,慼,慽,憇,憩,懠,戚,捿,掑,摖,斉,斊,旂,旗,晵,暣,朞,期,杞,柒,栔,栖,桤,桼,棄,棊,棋,棨,棲,榿,槭,檱,櫀,欫,欺,歧,气,気,氣,汔,汽,沏,泣,淇,淒,渏,湆,湇,漆,濝,炁,猉,玂,玘,琦,琪,璂,甈,畦,疧,盀,盵,矵,砌,碁,碕,碛,碶,磎,磜,磧,磩,礘,祁,祇,祈,祺,禥,竒,簯,簱,籏,粸,紪,綥,綦,綨,綮,綺,緀,緕,纃,绮,缼,罊,耆,肵,脐,臍,艩,芑,芞,芪,荠,萁,萋,葺,蕲,薺,藄,蘄,蚑,蚔,蚚,蛴,蜝,蜞,螧,蟿,蠐,裿,褀,褄,訖,諆,諬,諿,讫,豈,起,跂,踑,踦,蹊,軝,迄,迉,邔,郪,釮,錡,鏚,锜,闙,霋,頎,颀,騎,騏,騹,骐,骑,鬐,鬾,鬿,魌,魕,鯕,鰭,鲯,鳍,鵸,鶀,鶈,麒,麡,齊,齐,㒅,㓞,㜎,㞓,㞚,㟓,㟚,㟢,㣬,㥓,㩩,㩽,㫓,㮑,㯦,㼤,㾨,䀈,䀙,䁈,䁉,䄎,䄢,䄫,䅤,䅲,䉝,䉻,䋯,䌌,䎢,䏅,䏌,䏠,䏿,䐡,䑴,䒗,䒻,䓅,䔇,䙄,䚉,䚍,䛴,䞚,䟄,䟚,䡋,䡔,䢀,䧘,䧵,䩓,䫔,䬣,䭫,䭬,䭶,䭼,䰇,䰴,䱈,䲬,䳢,䶒,䶞|shang:丄,上,仩,伤,傷,商,垧,墒,尙,尚,恦,愓,慯,扄,晌,殇,殤,滳,漡,熵,緔,绱,蔏,螪,裳,觞,觴,謪,賞,赏,鑜,鬺,䬕|xia:丅,下,侠,俠,傄,匣,厦,吓,呷,嚇,圷,夏,夓,峡,峽,廈,懗,搳,敮,暇,柙,梺,溊,炠,烚,煆,狎,狭,狹,珨,瑕,疜,疨,睱,瞎,硖,硤,碬,磍,祫,笚,筪,縀,縖,罅,翈,舝,舺,蕸,虾,蝦,諕,谺,赮,轄,辖,遐,鍜,鎋,鏬,閕,閜,陜,陿,霞,颬,騢,魻,鰕,鶷,黠,㗇,㗿,㘡,㙤,㰺,㽠,䖎,䖖,䘥,䛅,䦖,䪗,䫗|mu:丆,亩,仫,凩,募,坶,墓,墲,姆,娒,峔,幕,幙,慔,慕,拇,旀,暮,木,椧,楘,樢,母,毣,毪,氁,沐,炑,牡,牧,牳,狇,獏,畆,畒,畝,畞,畮,目,睦,砪,穆,胟,艒,苜,莯,萺,蚞,踇,鉧,鉬,钼,雮,霂,鞪,㒇,㜈,㣎,㧅,㾇,䀲,䊾,䑵,䥈,䧔,䱯|wan:万,丸,乛,倇,刓,剜,卍,卐,唍,埦,塆,壪,妧,婉,婠,完,宛,岏,帵,弯,彎,忨,惋,抏,挽,捖,捥,晚,晩,晼,杤,梚,椀,汍,涴,湾,潫,灣,烷,玩,琓,琬,畹,皖,盌,睕,碗,笂,紈,綩,綰,纨,绾,翫,脘,腕,芄,莞,菀,萬,薍,蜿,豌,貦,贃,贎,踠,輓,邜,鋄,鋔,錽,鍐,鎫,頑,顽,㜶,㝴,㸘,㽜,㿸,䂺,䅋,䖤,䗕,䘼,䛷,䝹,䥑,䩊,䯈,䳃|zhang:丈,仉,仗,傽,墇,嫜,嶂,帐,帳,幛,幥,张,弡,張,彰,慞,扙,掌,暲,杖,樟,涨,涱,漲,漳,獐,璋,痮,瘬,瘴,瞕,礃,章,粀,粻,胀,脹,蔁,蟑,賬,账,遧,鄣,鏱,鐣,障,鞝,餦,騿,鱆,麞,㕩,㙣,㽴,䍤|san:三,伞,俕,傘,厁,叁,壭,弎,散,橵,毵,毶,毿,犙,糁,糂,糝,糣,糤,繖,鏒,閐,饊,馓,鬖,㤾,㧲,㪔,㪚,䀐,䉈,䊉,䫅,䫩|:|ji:丌,丮,乩,亟,亼,伋,伎,佶,偈,偮,僟,兾,冀,几,击,刉,刏,剂,剞,剤,劑,勣,卙,即,卽,及,叝,叽,吉,咭,哜,唧,喞,嗘,嘰,嚌,圾,坖,垍,基,塉,墍,墼,妀,妓,姞,姬,嫉,季,寂,寄,屐,岌,峜,嵆,嵇,嵴,嶯,己,幾,庴,廭,彐,彑,彶,徛,忌,忣,急,悸,惎,愱,憿,懻,戟,戢,技,挤,掎,揤,撃,撠,擊,擠,攲,敧,旡,既,旣,暨,暩,曁,机,极,枅,梞,棘,楖,楫,極,槉,槣,樭,機,橶,檕,檝,檵,櫅,殛,毄,汲,泲,洎,济,済,湒,漃,漈,潗,激,濈,濟,瀱,焏,犄,犱,狤,玑,璣,璾,畸,畿,疾,痵,瘠,癠,癪,皍,矶,磯,祭,禝,禨,积,稘,稩,稷,稽,穄,穊,積,穖,穧,笄,笈,筓,箕,箿,簊,籍,糭,紀,紒,級,継,緝,縘,績,繋,繫,繼,级,纪,继,绩,缉,罽,羁,羇,羈,耤,耭,肌,脊,脨,膌,臮,艥,芨,芰,芶,茍,萕,葪,蒺,蓟,蔇,蕀,蕺,薊,蘎,蘮,蘻,虀,虮,蝍,螏,蟣,裚,襀,襋,覉,覊,覬,觊,觙,觭,計,記,誋,諅,譏,譤,计,讥,记,谻,賫,賷,赍,趌,跡,跻,跽,踖,蹐,蹟,躋,躤,躸,輯,轚,辑,迹,郆,鄿,銈,銡,錤,鍓,鏶,鐖,鑇,鑙,际,際,隮,集,雞,雦,雧,霁,霵,霽,鞊,鞿,韲,飢,饑,饥,驥,骥,髻,魢,鮆,鯚,鯽,鰶,鰿,鱀,鱭,鱾,鲚,鲫,鳮,鵋,鶏,鶺,鷄,鷑,鸄,鸡,鹡,麂,齌,齎,齏,齑,㑧,㒫,㔕,㖢,㗊,㗱,㘍,㙨,㙫,㚡,㞃,㞆,㞛,㞦,㠍,㠎,㠖,㠱,㡇,㡭,㡮,㡶,㤂,㥍,㥛,㦸,㧀,㨈,㪠,㭰,㭲,㮟,㮨,㰟,㱞,㲅,㲺,㳵,㴉,㴕,㸄,㹄,㻑,㻷,㽺,㾊,㾒,㾵,䁒,䋟,䐀,䐕,䐚,䒁,䓫,䓽,䗁,䚐,䜞,䝸,䞘,䟌,䠏,䢋,䢳,䣢,䤒,䤠,䦇,䨖,䩯,䮺,䯂,䰏,䲯,䳭,䶓,䶩|bu:不,佈,勏,卟,吥,咘,哺,埗,埠,峬,布,庯,廍,怖,悑,捗,晡,步,歨,歩,獛,瓿,篰,簿,荹,蔀,补,補,誧,踄,轐,逋,部,郶,醭,鈈,鈽,钚,钸,餔,餢,鳪,鵏,鸔,㘵,㙛,㚴,㨐,㳍,㻉,㾟,䀯,䊇,䋠,䍌,䏽,䑰,䒈,䝵,䪁,䪔,䬏,䳝,䴝,䴺|yu:与,予,于,亐,伃,伛,余,俁,俞,俣,俼,偊,傴,儥,兪,匬,吁,唹,喅,喐,喩,喻,噊,噳,圄,圉,圫,域,堉,堣,堬,妤,妪,娛,娯,娱,媀,嫗,嬩,宇,寓,寙,屿,峪,峿,崳,嵎,嵛,嶎,嶼,庽,庾,彧,御,忬,悆,惐,愈,愉,愚,慾,懙,戫,扜,扵,挧,揄,敔,斔,斞,於,旟,昱,杅,栯,棛,棜,棫,楀,楡,楰,榆,櫲,欎,欝,欤,欲,歈,歟,歶,毓,浴,淢,淤,淯,渔,渝,湡,滪,漁,澞,澦,灪,焴,煜,燏,燠,爩,牏,狱,狳,獄,玉,玗,玙,琙,瑀,瑜,璵,畬,畭,瘀,瘉,瘐,癒,盂,盓,睮,矞,砡,硢,礇,礖,礜,祤,禦,禹,禺,秗,稢,稶,穥,穻,窬,窳,竽,箊,篽,籅,籞,籲,紆,緎,繘,纡,罭,羭,羽,聿,育,腴,臾,舁,舆,與,艅,芋,芌,茟,茰,荢,萭,萮,萸,蒮,蓣,蓹,蕍,蕷,薁,蘌,蘛,虞,虶,蜟,蜮,蝓,螸,衧,袬,裕,褕,覦,觎,誉,語,諛,諭,謣,譽,语,谀,谕,豫,貐,踰,軉,輍,輿,轝,迃,逳,逾,遇,遹,邘,郁,鄅,酑,醧,釪,鈺,銉,鋊,鋙,錥,鍝,鐭,钰,铻,閾,阈,陓,隃,隅,隩,雓,雨,雩,霱,預,预,飫,餘,饇,饫,馀,馭,騟,驈,驭,骬,髃,鬰,鬱,鬻,魊,魚,魣,鮽,鯲,鰅,鱊,鱼,鳿,鴥,鴧,鴪,鵒,鷠,鷸,鸆,鸒,鹆,鹬,麌,齬,龉,㑨,㒁,㒜,㔱,㙑,㚥,㝢,㠘,㠨,㡰,㣃,㤤,㥔,㥚,㥥,㦛,㪀,㬂,㬰,㲾,㳚,㳛,㶛,㷒,㺄,㺞,㺮,㼌,㼶,㽣,䁌,䁩,䂊,䂛,䃋,䄏,䄨,䆷,䈅,䉛,䋖,䍂,䍞,䏸,䐳,䔡,䖇,䗨,䘘,䘱,䛕,䜽,䢓,䢩,䣁,䥏,䨒,䨞,䩒,䬄,䮇,䮙,䰻,䱷,䲣,䴁,䵫|mian:丏,俛,偭,免,冕,勉,勔,喕,娩,婂,媔,嬵,宀,愐,棉,檰,櫋,汅,沔,湎,眄,眠,矈,矊,矏,糆,綿,緜,緬,绵,缅,腼,臱,芇,葂,蝒,面,靣,鮸,麪,麫,麵,麺,黾,㒙,㛯,㝰,㤁,㬆,㮌,㰃,㴐,㻰,䀎,䃇,䏃,䤄,䫵,䰓|gai:丐,乢,侅,匃,匄,垓,姟,峐,忋,戤,摡,改,晐,杚,概,槩,槪,溉,漑,瓂,畡,盖,祴,絠,絯,荄,葢,蓋,該,该,豥,賅,賌,赅,郂,鈣,鎅,钙,陔,隑,㕢,㧉,㮣,䏗,䪱|chou:丑,丒,仇,侴,俦,偢,儔,吜,嬦,帱,幬,惆,愁,懤,抽,搊,杽,栦,椆,殠,燽,犨,犫,畴,疇,瘳,皗,瞅,矁,稠,筹,篘,籌,紬,絒,綢,绸,臭,臰,菗,薵,裯,詶,讎,讐,踌,躊,遚,酧,酬,醜,醻,雔,雠,魗,㐜,㛶,㤽,㦞,㨶,㵞,㿧,䇺,䊭,䌧,䌷,䓓,䔏,䛬,䥒,䪮,䲖|zhuan:专,僎,叀,啭,囀,堟,嫥,孨,専,專,撰,灷,瑑,瑼,甎,砖,磚,竱,篆,籑,縳,膞,蒃,蟤,襈,諯,譔,賺,赚,転,轉,转,鄟,顓,颛,饌,馔,鱄,䉵,䡱|qie:且,倿,切,匧,厒,妾,怯,悏,惬,愜,挈,朅,洯,淁,癿,穕,窃,竊,笡,箧,篋,籡,緁,聺,苆,茄,藒,蛪,踥,鍥,鐑,锲,魥,鯜,㓶,㗫,㚗,㛍,㛙,㤲,㥦,㫸,㰰,㰼,㹤,㾀,㾜,䟙,䤿,䦧,䬊|pi:丕,仳,伓,伾,僻,劈,匹,啤,噼,噽,嚊,嚭,圮,坯,埤,壀,媲,嫓,屁,岯,崥,庀,怶,悂,憵,批,披,抷,揊,擗,旇,朇,枇,椑,榌,毗,毘,毞,淠,渒,潎,澼,炋,焷,狉,狓,琵,甓,疈,疲,痞,癖,皮,睤,睥,砒,磇,礔,礕,秛,秠,笓,篺,簲,紕,纰,罴,羆,翍,耚,肶,脴,脾,腗,膍,芘,苉,蚍,蚽,蜱,螷,蠯,諀,譬,豼,豾,貔,邳,郫,釽,鈚,鈹,鉟,銔,銢,錃,錍,铍,闢,阰,陴,隦,霹,駓,髬,魮,魾,鮍,鲏,鴄,鵧,鷿,鸊,鼙,㔥,㨽,㯅,㿙,䏘,䑀,䑄,䚰,䚹,䠘,䡟,䤏,䤨,䫌,䰦,䴙|shi:世,丗,乨,亊,事,什,仕,佦,使,侍,兘,兙,冟,势,勢,十,卋,叓,史,呞,呩,嗜,噬,埘,塒,士,失,奭,始,姼,嬕,实,実,室,宩,寔,實,尸,屍,屎,峕,崼,嵵,市,师,師,式,弑,弒,徥,忕,恀,恃,戺,拭,拾,揓,施,时,旹,是,昰,時,枾,柹,柿,栻,榁,榯,檡,氏,浉,湜,湤,湿,溡,溮,溼,澨,濕,炻,烒,煶,狮,獅,瑡,瓧,眂,眎,眡,睗,矢,石,示,礻,祏,竍,笶,笹,筮,箷,篒,簭,籂,籭,絁,舐,舓,莳,葹,蒒,蒔,蓍,虱,虲,蚀,蝕,蝨,螫,褆,褷,襫,襹,視,视,觢,試,詩,誓,諟,諡,謚,識,识,试,诗,谥,豕,貰,贳,軾,轼,辻,适,逝,遈,適,遾,邿,酾,釃,釈,释,釋,釶,鈰,鉂,鉃,鉇,鉐,鉽,銴,鍦,铈,食,飠,飾,餝,饣,饰,駛,驶,鮖,鯴,鰘,鰣,鰤,鲥,鲺,鳲,鳾,鶳,鸤,鼫,鼭,齛,㒾,㔺,㕜,㖷,㫑,㮶,㱁,㵓,㸷,㹝,㹬,㹷,䁺,䂖,䊓,䏡,䒨,䖨,䛈,䟗,䤱,䦠,䦹,䩃,䭄,䰄,䴓,䶡|qiu:丘,丠,俅,叴,唒,囚,坵,媝,寈,崷,巯,巰,恘,扏,搝,朹,梂,楸,殏,毬,求,汓,泅,浗,渞,湭,煪,犰,玌,球,璆,皳,盚,秋,秌,穐,篍,糗,紌,絿,緧,肍,莍,萩,蓲,蘒,虬,虯,蚯,蛷,蝤,蝵,蟗,蠤,裘,觓,觩,訄,訅,賕,赇,趥,逎,逑,遒,邱,酋,醔,釚,釻,銶,鞦,鞧,鮂,鯄,鰌,鰍,鰽,鱃,鳅,鵭,鶖,鹙,鼽,龝,㐀,㐤,㕤,㞗,㟈,㤹,㥢,㧨,㭝,㷕,㺫,㼒,䆋,䊵,䎿,䜪,䞭,䟬,䟵,䠗,䣇,䤛|bing:丙,並,仌,併,倂,偋,傡,兵,冫,冰,垪,寎,并,幷,庰,怲,抦,掤,摒,昞,昺,柄,栟,栤,梹,棅,檳,氷,炳,燷,病,眪,禀,秉,窉,竝,苪,蛃,誁,邴,鈵,鉼,鋲,陃,靐,鞆,餅,餠,饼,鮩,㓈,㨀,䈂,䋑,䓑,䗒,䴵|ye:业,也,亪,亱,倻,偞,僷,冶,叶,吔,嘢,噎,嚈,埜,堨,墷,壄,夜,嶪,嶫,抴,捓,捙,掖,揶,擖,擛,擨,擪,擫,晔,暍,曄,曅,曗,曳,枼,枽,椰,楪,業,歋,殗,洂,液,漜,潱,澲,烨,燁,爗,爷,爺,皣,瞱,瞸,礏,耶,腋,葉,蠮,謁,谒,邺,鄓,鄴,野,釾,鋣,鍱,鎁,鎑,铘,靥,靨,頁,页,餣,饁,馌,驜,鵺,鸈,㐖,㖡,㖶,㗼,㙒,㙪,㝣,㥷,㩎,㪑,㱉,㸣,䈎,䓉,䤳,䤶,䥟,䥡,䥺,䧨,䭟,䲜|cong:丛,从,匆,叢,囪,囱,婃,孮,従,徖,從,忩,怱,悤,悰,慒,憁,暰,枞,棇,楤,樅,樬,樷,欉,淙,漎,漗,潀,潈,潨,灇,焧,熜,爜,琮,瑽,璁,瞛,篵,緫,繱,聡,聦,聪,聰,苁,茐,葱,蓯,蔥,藂,蟌,誴,謥,賨,賩,鏦,騘,驄,骢,㼻,䉘,䕺,䧚,䳷|dong:东,侗,倲,働,冬,冻,凍,动,動,咚,垌,埬,墥,姛,娻,嬞,岽,峒,峝,崠,崬,恫,懂,戙,挏,昸,東,栋,棟,氡,氭,洞,涷,湩,硐,笗,箽,胨,胴,腖,苳,菄,董,蕫,蝀,詷,諌,迵,霘,駧,鮗,鯟,鶇,鶫,鸫,鼕,㑈,㓊,㖦,㗢,㜱,㢥,㨂,㼯,䂢,䅍,䍶,䞒,䵔|si:丝,乺,亖,伺,似,佀,価,俟,俬,儩,兕,凘,厮,厶,司,咝,嗣,嘶,噝,四,姒,娰,媤,孠,寺,巳,廝,思,恖,撕,斯,枱,柶,梩,楒,榹,死,汜,泀,泗,泤,洍,涘,澌,瀃,燍,牭,磃,祀,禗,禠,禩,私,竢,笥,糹,絲,緦,纟,缌,罒,罳,耜,肂,肆,蕬,蕼,虒,蛳,蜤,螄,螦,蟖,蟴,覗,貄,釲,鈻,鉰,銯,鋖,鍶,鐁,锶,颸,飔,飤,飼,饲,駟,騃,騦,驷,鷥,鸶,鼶,㐌,㕽,㚶,㣈,㭒,㸻,㹑,㾅,䇃,䎣,䏤,䦙|cheng:丞,乗,乘,侱,偁,呈,城,埕,堘,塍,塖,娍,宬,峸,庱,徎,悜,惩,憆,憕,懲,成,承,挰,掁,摚,撐,撑,朾,枨,柽,棖,棦,椉,橕,橙,檉,檙,泟,洆,浾,溗,澂,澄,瀓,爯,牚,珵,珹,琤,畻,睈,瞠,碀,秤,称,程,穪,窚,竀,筬,絾,緽,脀,脭,荿,虰,蛏,蟶,裎,誠,诚,赪,赬,逞,郕,酲,鋮,鏳,鏿,鐺,铖,铛,阷,靗,頳,饓,騁,騬,骋,鯎,㐼,㞼,㨃,㲂,㼩,䀕,䁎,䄇,䆑,䆵,䆸,䇸,䔲,䗊,䞓,䧕,䫆,䮪|diu:丟,丢,銩,铥,颩|liang:両,两,亮,俍,兩,凉,哴,唡,啢,喨,墚,掚,晾,梁,椋,樑,涼,湸,煷,簗,粮,粱,糧,綡,緉,脼,良,蜽,裲,諒,谅,踉,輌,輛,輬,辆,辌,量,鍄,魉,魎,㒳,㔝,㹁,䓣,䝶,䠃,䣼,䩫,䭪|you:丣,亴,优,佑,侑,偤,優,卣,又,友,右,呦,哊,唀,嚘,囿,姷,孧,宥,尢,尤,峟,峳,幼,幽,庮,忧,怞,怣,怮,悠,憂,懮,攸,斿,有,柚,梄,梎,楢,槱,櫌,櫾,沋,油,泑,浟,游,湵,滺,瀀,牖,牗,牰,犹,狖,猶,猷,由,疣,祐,禉,秞,糿,纋,羐,羑,耰,聈,肬,脜,苃,莜,莠,莤,莸,蒏,蕕,蚰,蚴,蜏,蝣,訧,誘,诱,貁,輏,輶,迂,迶,逌,逰,遊,邎,邮,郵,鄾,酉,酭,釉,鈾,銪,铀,铕,駀,魷,鮋,鱿,鲉,麀,黝,鼬,㒡,㓜,㕗,㕱,㘥,㚭,㛜,㤑,㫍,㮋,㰶,㳺,㹨,㺠,㻀,㽕,㾞,䀁,䅎,䆜,䑻,䒴,䖻,䚃,䛻,䞥,䢊,䢟,䬀,䱂,䳑|yan:严,乵,俨,偃,偐,偣,傿,儼,兖,兗,円,剦,匽,厌,厣,厭,厳,厴,咽,唁,喭,噞,嚥,嚴,堰,塩,墕,壛,壧,夵,奄,妍,妟,姲,姸,娫,娮,嫣,嬊,嬮,嬿,孍,宴,岩,崦,嵃,嵒,嵓,嶖,巌,巖,巗,巘,巚,延,弇,彥,彦,恹,愝,懕,戭,扊,抁,掞,掩,揅,揜,敥,昖,晏,暥,曕,曮,棪,椻,椼,楌,樮,檐,檿,櫩,欕,沇,沿,淹,渰,渷,湮,滟,演,漹,灎,灔,灧,灩,炎,烟,焉,焔,焰,焱,煙,熖,燄,燕,爓,牪,狿,猒,珚,琂,琰,甗,盐,眼,研,砚,硏,硯,硽,碞,礹,筵,篶,簷,綖,縯,罨,胭,腌,臙,艳,艶,艷,芫,莚,菸,萒,葕,蔅,虤,蜒,蝘,衍,裺,褗,覎,觃,觾,言,訁,訮,詽,諺,讌,讞,讠,谚,谳,豓,豔,贋,贗,贘,赝,躽,軅,遃,郔,郾,鄢,酀,酓,酽,醃,醶,醼,釅,閆,閹,閻,闫,阉,阎,隁,隒,雁,顏,顔,顩,颜,餍,饜,騐,験,騴,驗,驠,验,鬳,魇,魘,鰋,鳫,鴈,鴳,鶠,鷃,鷰,鹽,麙,麣,黡,黤,黫,黬,黭,黶,鼴,鼹,齞,齴,龑,㓧,㕣,㗴,㘖,㘙,㚧,㛪,㢂,㢛,㦔,㫃,㫟,㬫,㭺,㳂,㶄,㷔,㷳,㷼,㿕,㿼,䀋,䀽,䁙,䂩,䂴,䄋,䅧,䊙,䊻,䌪,䎦,䑍,䓂,䕾,䖗,䗡,䗺,䜩,䢥,䢭,䣍,䤷,䨄,䭘,䱲,䲓,䳛,䳺,䴏,䶮|sang:丧,喪,嗓,搡,桑,桒,槡,磉,褬,鎟,顙,颡,䡦,䫙|gun:丨,惃,棍,棞,滚,滾,璭,睔,睴,磙,緄,緷,绲,蓘,蔉,衮,袞,裷,謴,輥,辊,鮌,鯀,鲧,㙥,㫎,㯻,䃂,䎾,䜇,䵪|jiu:丩,久,乆,九,乣,倃,僦,勼,匓,匛,匶,厩,咎,啾,奺,就,廄,廏,廐,慦,揂,揪,揫,摎,救,旧,朻,杦,柩,柾,桕,樛,欍,殧,汣,灸,牞,玖,畂,疚,究,糺,糾,紤,纠,臼,舅,舊,舏,萛,赳,酒,镹,阄,韭,韮,鬏,鬮,鯦,鳩,鷲,鸠,鹫,麔,齨,㠇,㡱,㧕,㩆,㲃,㶭,㺩,㺵,䅢,䆒,䊆,䊘,䓘,䛮,䡂,䳎,䳔|ge:个,佮,個,割,匌,各,呄,哥,哿,嗝,圪,塥,彁,愅,戈,戓,戨,挌,搁,搿,擱,敋,格,槅,櫊,歌,滆,滒,牫,牱,犵,獦,疙,硌,箇,紇,纥,肐,胳,膈,臵,舸,茖,葛,虼,蛒,蛤,袼,裓,觡,諽,謌,輵,轕,鉻,鎘,鎶,铬,镉,閣,閤,阁,隔,革,鞈,鞷,韐,韚,騔,骼,鬲,鮯,鰪,鴐,鴚,鴿,鸽,㗆,㝓,㠷,㦴,㨰,㪾,㵧,㷴,䆟,䈓,䐙,䕻,䗘,䘁,䛋,䛿,䢔,䧄,䨣,䩐,䪂,䪺,䫦|ya:丫,亚,亜,亞,伢,俹,劜,厊,压,厓,呀,哑,唖,啞,圔,圠,垭,埡,堐,壓,娅,婭,孲,岈,崕,崖,庌,庘,押,挜,掗,揠,枒,桠,椏,氩,氬,涯,漄,牙,犽,猚,猰,玡,琊,瑘,疋,痖,瘂,睚,砑,稏,穵,窫,笌,聐,芽,蕥,蚜,衙,襾,訝,讶,迓,錏,鐚,铔,雅,鴉,鴨,鵶,鸦,鸭,齖,齾,㝞,㧎,㰳,㿿,䄰,䅉,䊦,䝟,䢝,䦪,䪵,䯉,䰲,䵝|zhuang:丬,壮,壯,壵,妆,妝,娤,庄,庒,戅,撞,桩,梉,樁,湷,焋,状,狀,粧,糚,荘,莊,装,裝|zhong:中,仲,伀,众,偅,冢,刣,喠,堹,塚,妐,妕,媑,尰,幒,彸,忠,柊,歱,汷,泈,炂,煄,狆,瘇,盅,眾,祌,祍,种,種,筗,籦,終,终,肿,腫,舯,茽,蔠,蚛,螤,螽,衆,衳,衶,衷,諥,踵,蹱,迚,重,鈡,鍾,鐘,钟,锺,鴤,鼨,㐺,㣫,㲴,䱰|jie:丯,介,借,倢,偼,傑,刦,刧,刼,劫,劼,卩,卪,吤,喈,嗟,堦,堺,姐,婕,媎,媘,媫,嫅,孑,尐,屆,届,岊,岕,崨,嵥,嶻,巀,幯,庎,徣,忦,悈,戒,截,拮,捷,接,掲,揭,擑,擮,擳,斺,昅,杰,桀,桔,桝,椄,楐,楬,楶,榤,檞,櫭,毑,洁,湝,滐,潔,煯,犗,玠,琾,界,畍,疌,疖,疥,痎,癤,皆,睫,砎,碣,礍,秸,稭,竭,節,結,繲,结,羯,脻,节,芥,莭,菨,蓵,藉,蚧,蛣,蛶,蜐,蝔,蠘,蠞,蠽,街,衱,衸,袺,褯,解,觧,訐,詰,誡,誱,讦,诘,诫,踕,迼,鉣,鍻,阶,階,鞂,頡,颉,飷,骱,魝,魪,鮚,鲒,鶛,㑘,㓗,㓤,㔾,㘶,㛃,㝌,㝏,㞯,㠹,㦢,㨗,㨩,㮞,㮮,㸅,㾏,㿍,䀷,䀹,䁓,䂒,䂝,䂶,䅥,䇒,䌖,䔿,䕙,䗻,䛺,䣠,䥛,䯰,䰺,䱄,䲙,䲸|feng:丰,仹,俸,偑,僼,冯,凤,凨,凬,凮,唪,堸,夆,奉,妦,寷,封,峯,峰,崶,捀,摓,枫,桻,楓,檒,沣,沨,浲,渢,湗,溄,灃,烽,焨,煈,犎,猦,琒,瓰,甮,疯,瘋,盽,砜,碸,篈,綘,縫,缝,艂,葑,蘕,蘴,蜂,覂,諷,讽,豐,賵,赗,逢,鄷,酆,鋒,鎽,鏠,锋,靊,風,飌,风,馮,鳯,鳳,鴌,麷,㡝,㦀,㵯,䏎,䙜,䟪,䩼|guan:丱,倌,关,冠,卝,官,悹,悺,惯,慣,掼,摜,棺,樌,毌,泴,涫,潅,灌,爟,琯,瓘,痯,瘝,癏,盥,矔,礶,祼,窤,筦,管,罆,罐,舘,萖,蒄,覌,観,觀,观,貫,贯,躀,輨,遦,錧,鏆,鑵,関,闗,關,雚,館,馆,鰥,鱞,鱹,鳏,鳤,鸛,鹳,㮡,㴦,䌯,䎚,䏓,䗆,䗰,䘾,䙛,䙮,䝺,䦎,䩪,䪀,䲘|chuan:串,传,傳,僢,剶,喘,圌,巛,川,暷,椽,歂,氚,汌,猭,玔,瑏,穿,篅,舛,舡,舩,船,荈,賗,輲,遄,釧,钏,镩,鶨,㯌,㱛,㼷,䁣|chan:丳,产,僝,儃,儳,冁,刬,剗,剷,劖,嚵,囅,壥,婵,嬋,孱,嵼,巉,幝,幨,廛,忏,懴,懺,掺,搀,摌,摲,摻,攙,旵,梴,棎,欃,毚,浐,湹,滻,潹,潺,瀍,瀺,灛,煘,燀,獑,產,産,硟,磛,禅,禪,簅,緾,繟,繵,纏,纒,缠,羼,艬,蒇,蕆,蝉,蝊,蟬,蟾,裧,襜,覘,觇,誗,諂,譂,讇,讒,谄,谗,躔,辿,鄽,酁,醦,鋋,鋓,鏟,鑱,铲,镡,镵,閳,闡,阐,韂,顫,颤,饞,馋,㔆,㙴,㙻,㢆,㢟,㦃,㬄,㯆,㵌,㶣,㸥,㹌,㹽,㺥,䀡,䂁,䊲,䐮,䑎,䜛,䠨,䡪,䡲,䣑,䤘,䤫,䥀,䧯,䩶,䪜,䮭,䱿,䴼,䵐|lin:临,亃,僯,凛,凜,厸,吝,啉,壣,崊,嶙,廩,廪,恡,悋,惏,懍,懔,拎,撛,斴,晽,暽,林,橉,檁,檩,淋,潾,澟,瀶,焛,燐,獜,琳,璘,甐,疄,痳,癛,癝,瞵,碄,磷,稟,箖,粦,粼,繗,翷,膦,臨,菻,蔺,藺,賃,赁,蹸,躏,躙,躪,轔,轥,辚,遴,邻,鄰,鏻,閵,隣,霖,顲,驎,鱗,鳞,麐,麟,㐭,㔂,㖁,㝝,㨆,㷠,䉮,䕲,䗲,䚬,䢯,䫐,䫰,䮼|zhuo:丵,倬,劅,卓,叕,啄,啅,圴,妰,娺,彴,拙,捉,撯,擆,擢,斀,斫,斮,斱,斲,斵,晫,桌,梲,棁,棳,椓,槕,櫡,浊,浞,涿,濁,濯,灂,灼,炪,烵,犳,琢,琸,着,硺,禚,穛,穱,窡,窧,篧,籗,籱,罬,茁,蠗,蠿,諁,諑,謶,诼,酌,鋜,鐯,鐲,镯,鵫,鷟,㑁,㣿,㪬,㭬,㺟,䅵,䕴,䶂|zhu:丶,主,伫,佇,住,侏,劚,助,劯,嘱,囑,坾,墸,壴,孎,宔,屬,嵀,拄,斸,曯,朱,杼,柱,柷,株,槠,樦,橥,櫧,櫫,欘,殶,泏,注,洙,渚,潴,濐,瀦,灟,炢,炷,烛,煑,煮,燭,爥,猪,珠,疰,瘃,眝,瞩,矚,砫,硃,祝,祩,秼,窋,竚,竹,竺,笁,笜,筑,筯,箸,築,篫,紵,紸,絑,纻,罜,羜,翥,舳,芧,苎,苧,茱,茿,莇,著,蓫,藸,蛀,蛛,蝫,蠋,蠩,蠾,袾,註,詝,誅,諸,诛,诸,豬,貯,贮,跓,跦,躅,軴,迬,逐,邾,鉒,銖,鋳,鑄,钃,铢,铸,陼,霔,飳,馵,駐,駯,驻,鮢,鯺,鱁,鴸,麆,麈,鼄,㑏,㔉,㝉,㤖,㧣,㫂,㵭,㹥,㺛,㾻,㿾,䇡,䇧,䌵,䍆,䎷,䐢,䕽,䘚,䘢,䝒,䝬,䟉,䥮,䬡,䭖,䮱,䰞|ha:丷,哈,妎,鉿,铪|dan:丹,亶,伔,但,僤,儋,刐,勯,匰,单,単,啖,啗,啿,單,嘾,噉,嚪,妉,媅,帎,弹,彈,惮,憚,憺,担,掸,撣,擔,旦,柦,殚,殫,氮,沊,泹,淡,澸,澹,狚,玬,瓭,甔,疍,疸,瘅,癉,癚,眈,砃,禫,窞,箪,簞,紞,耼,耽,聃,聸,胆,腅,膽,萏,蛋,蜑,衴,褝,襌,觛,訑,誕,诞,贉,躭,郸,鄲,酖,霮,頕,餤,饏,馾,駳,髧,鴠,黕,㔊,㕪,㗖,㡺,㫜,㱽,㲷,㵅,㺗,㽎,䃫,䄷,䉞,䉷,䨢,䨵,䩥,䭛,䮰,䱋,䳉|wei:为,亹,伟,伪,位,偉,偎,偽,僞,儰,卫,危,厃,叞,味,唯,喂,喡,喴,囗,围,圍,圩,墛,壝,委,威,娓,媁,媙,媦,寪,尉,尾,峗,峞,崣,嵔,嵬,嶶,巍,帏,帷,幃,廆,徫,微,惟,愄,愇,慰,懀,捤,揋,揻,斖,昷,暐,未,桅,梶,椲,椳,楲,沩,洈,洧,浘,涠,渨,渭,湋,溈,溦,潍,潙,潿,濊,濰,濻,瀢,炜,為,烓,煀,煒,煟,煨,熭,燰,爲,犚,犩,猥,猬,玮,琟,瑋,璏,畏,痏,痿,癐,癓,硊,硙,碨,磑,維,緭,緯,縅,纬,维,罻,胃,腲,艉,芛,苇,苿,荱,菋,萎,葦,葨,葳,蒍,蓶,蔚,蔿,薇,薳,藯,蘶,蜲,蜼,蝛,蝟,螱,衛,衞,褽,覣,覹,詴,諉,謂,讆,讏,诿,谓,踓,躗,躛,軎,轊,违,逶,違,鄬,醀,錗,鍏,鍡,鏏,闈,闱,隇,隈,隗,霨,霺,霻,韋,韑,韙,韡,韦,韪,頠,颹,餧,餵,饖,骩,骪,骫,魏,鮇,鮠,鮪,鰃,鰄,鲔,鳂,鳚,㕒,㖐,㞇,㞑,㟪,㠕,㢻,㣲,㥜,㦣,㧑,㨊,㬙,㭏,㱬,㷉,䃬,䈧,䉠,䑊,䔺,䗽,䘙,䙿,䜅,䜜,䝐,䞔,䡺,䥩,䧦,䪋,䪘,䬐,䬑,䬿,䭳,䮹,䲁,䵋,䵳|jing:丼,井,京,亰,俓,倞,傹,儆,兢,净,凈,刭,剄,坓,坕,坙,境,妌,婙,婛,婧,宑,巠,幜,弪,弳,径,徑,惊,憬,憼,敬,旌,旍,景,晶,暻,曔,桱,梷,橸,汫,汬,泾,浄,涇,淨,瀞,燝,燞,猄,獍,璄,璟,璥,痉,痙,睛,秔,稉,穽,竞,竟,竧,竫,競,竸,粳,精,経,經,经,聙,肼,胫,脛,腈,茎,荆,荊,莖,菁,蟼,誩,警,踁,迳,逕,鏡,镜,阱,靓,靖,静,靚,靜,頚,頸,颈,驚,鯨,鲸,鵛,鶁,鶄,麖,麠,鼱,㕋,㘫,㢣,㣏,㬌,㵾,㹵,䔔,䜘,䡖,䴖,䵞|li:丽,例,俐,俚,俪,傈,儮,儷,凓,刕,利,剓,剺,劙,力,励,勵,历,厉,厘,厤,厯,厲,吏,呖,哩,唎,唳,喱,嚟,嚦,囄,囇,坜,塛,壢,娌,娳,婯,嫠,孋,孷,屴,岦,峛,峲,巁,廲,悡,悧,悷,慄,戾,搮,攊,攦,攭,斄,暦,曆,曞,朸,李,枥,栃,栎,栗,栛,栵,梨,梸,棃,棙,樆,檪,櫔,櫟,櫪,欐,欚,歴,歷,氂,沥,沴,浬,涖,溧,漓,澧,濿,瀝,灕,爄,爏,犁,犂,犛,犡,狸,猁,珕,理,琍,瑮,璃,瓅,瓈,瓑,瓥,疠,疬,痢,癘,癧,皪,盠,盭,睝,砅,砺,砾,磿,礪,礫,礰,礼,禮,禲,离,秝,穲,立,竰,笠,筣,篥,篱,籬,粒,粝,粴,糎,糲,綟,縭,缡,罹,艃,苈,苙,茘,荔,荲,莅,莉,菞,蒚,蒞,蓠,蔾,藜,藶,蘺,蚸,蛎,蛠,蜊,蜧,蟍,蟸,蠇,蠡,蠣,蠫,裏,裡,褵,詈,謧,讈,豊,貍,赲,跞,躒,轢,轣,轹,逦,邌,邐,郦,酈,醨,醴,里,釐,鉝,鋫,鋰,錅,鏫,鑗,锂,隶,隷,隸,離,雳,靂,靋,驪,骊,鬁,鯉,鯏,鯬,鱧,鱱,鱺,鲡,鲤,鳢,鳨,鴗,鵹,鷅,鸝,鹂,麗,麜,黎,黧,㑦,㒧,㒿,㓯,㔏,㕸,㗚,㘑,㟳,㠟,㡂,㤡,㤦,㦒,㧰,㬏,㮚,㯤,㰀,㰚,㱹,㴝,㷰,㸚,㹈,㺡,㻎,㻺,㼖,㽁,㽝,㾐,㾖,㿛,㿨,䁻,䃯,䄜,䅄,䅻,䇐,䉫,䊍,䊪,䋥,䍠,䍦,䍽,䓞,䔁,䔆,䔉,䔣,䔧,䖥,䖽,䖿,䗍,䘈,䙰,䚕,䟏,䟐,䡃,䣓,䣫,䤙,䤚,䥶,䧉,䬅,䬆,䮋,䮥,䰛,䰜,䱘,䲞,䴄,䴡,䴻,䵓,䵩,䶘|ju:举,侷,俱,倨,倶,僪,具,冣,凥,剧,劇,勮,匊,句,咀,圧,埧,埾,壉,姖,娵,婅,婮,寠,局,居,屦,屨,岠,崌,巈,巨,弆,怇,怚,惧,愳,懅,懼,抅,拒,拘,拠,挙,挶,捄,据,掬,據,擧,昛,梮,椇,椈,椐,榉,榘,橘,檋,櫸,欅,歫,毩,毱,沮,泃,泦,洰,涺,淗,湨,澽,炬,焗,焣,爠,犋,犑,狊,狙,琚,疽,痀,眗,瞿,矩,砠,秬,窭,窶,筥,簴,粔,粷,罝,耟,聚,聥,腒,舉,艍,苣,苴,莒,菊,蒟,蓻,蘜,虡,蚷,蜛,袓,裾,襷,詎,諊,讵,豦,貗,趄,趜,跔,跙,距,跼,踘,踞,踽,蹫,躆,躹,輂,遽,邭,郹,醵,鉅,鋦,鋸,鐻,钜,锔,锯,閰,陱,雎,鞠,鞫,颶,飓,駏,駒,駶,驧,驹,鮈,鮔,鴡,鵙,鵴,鶋,鶪,鼰,鼳,齟,龃,㘌,㘲,㜘,㞐,㞫,㠪,㥌,㨿,㩀,㩴,㬬,㮂,㳥,㽤,䃊,䄔,䅓,䆽,䈮,䋰,䏱,䕮,䗇,䛯,䜯,䡞,䢹,䣰,䤎,䪕,䰬,䱟,䱡,䴗,䵕,䶙,䶥|pie:丿,嫳,撆,撇,暼,氕,瞥,苤,鐅,䥕|fu:乀,付,伏,伕,俌,俘,俯,偩,傅,冨,冹,凫,刜,副,匐,呋,呒,咈,咐,哹,坿,垘,复,夫,妇,妋,姇,娐,婏,婦,媍,孚,孵,富,尃,岪,峊,巿,帗,幅,幞,府,弗,弣,彿,復,怤,怫,懯,扶,抚,拂,拊,捬,撫,敷,斧,旉,服,枎,枹,柎,柫,栿,桴,棴,椨,椱,榑,氟,泭,洑,浮,涪,滏,澓,炥,烰,焤,父,猤,玞,玸,琈,甫,甶,畉,畐,畗,癁,盙,砆,砩,祓,祔,福,禣,秿,稃,稪,竎,符,笰,筟,箙,簠,粰,糐,紨,紱,紼,絥,綍,綒,緮,縛,绂,绋,缚,罘,罦,翇,肤,胕,脯,腐,腑,腹,膚,艀,艴,芙,芣,芾,苻,茀,茯,荂,荴,莩,菔,萯,葍,蕧,虙,蚥,蚨,蚹,蛗,蜅,蜉,蝜,蝠,蝮,衭,袝,袱,複,褔,襆,襥,覄,覆,訃,詂,諨,讣,豧,負,賦,賻,负,赋,赙,赴,趺,跗,踾,輔,輹,輻,辅,辐,邞,郙,郛,鄜,酜,釜,釡,鈇,鉘,鉜,鍑,鍢,阜,阝,附,陚,韍,韨,颫,馥,駙,驸,髴,鬴,鮄,鮒,鮲,鰒,鲋,鳆,鳧,鳬,鳺,鴔,鵩,鶝,麩,麬,麱,麸,黻,黼,㓡,㕮,㙏,㚆,㚕,㜑,㟊,㠅,㤔,㤱,㪄,㫙,㬼,㳇,㵗,㽬,㾈,䂤,䃽,䋨,䋹,䌗,䌿,䍖,䎅,䑧,䒀,䒇,䓛,䔰,䕎,䗄,䘀,䘄,䘠,䝾,䞜,䞞,䞯,䞸,䟔,䟮,䠵,䡍,䦣,䧞,䨗,䨱,䩉,䪙,䫍,䫝,䭸,䮛,䯱,䯽,䵗,䵾|nai:乃,倷,奈,奶,妳,嬭,孻,廼,摨,柰,氖,渿,熋,疓,耐,腉,艿,萘,螚,褦,迺,釢,錼,鼐,㮈,㮏,㲡,㾍,䍲,䘅,䯮|wu:乄,乌,五,仵,伆,伍,侮,俉,倵,儛,兀,剭,务,務,勿,午,吳,吴,吾,呉,呜,唔,啎,嗚,圬,坞,塢,奦,妩,娪,娬,婺,嫵,寤,屋,屼,岉,嵍,嵨,巫,庑,廡,弙,忢,忤,怃,悞,悟,悮,憮,戊,扤,捂,摀,敄,无,旿,晤,杇,杌,梧,橆,歍,武,毋,汙,汚,污,洖,洿,浯,溩,潕,烏,焐,焑,無,熃,熓,物,牾,玝,珷,珸,瑦,璑,甒,痦,矹,碔,祦,禑,窏,窹,箼,粅,舞,芜,芴,茣,莁,蕪,蘁,蜈,螐,誈,誣,誤,诬,误,趶,躌,迕,逜,邬,郚,鄔,釫,鋈,錻,鎢,钨,阢,隖,雾,霚,霧,靰,騖,骛,鯃,鰞,鴮,鵐,鵡,鶩,鷡,鹀,鹉,鹜,鼯,鼿,齀,㐅,㐳,㑄,㡔,㬳,㵲,㷻,㹳,㻍,㽾,䃖,䍢,䎸,䑁,䒉,䛩,䟼,䡧,䦍,䦜,䫓,䮏,䳇,䳱|tuo:乇,佗,侂,侻,咃,唾,坨,堶,妥,媠,嫷,岮,庹,彵,托,扡,拓,拕,拖,挩,捝,撱,杔,柁,柝,椭,楕,槖,橐,橢,毤,毻,汑,沰,沱,涶,狏,砣,砤,碢,箨,籜,紽,脫,脱,莌,萚,蘀,袉,袥,託,詑,讬,跅,跎,踻,迱,酡,陀,陁,飥,饦,馱,馲,駄,駝,駞,騨,驒,驝,驮,驼,魠,鮀,鰖,鴕,鵎,鸵,鼉,鼍,鼧,㟎,㸰,㸱,㼠,㾃,䍫,䓕,䡐,䪑,䭾,䰿,䲊,䴱|me:么,嚒,嚰,庅,濹,癦|ho:乊,乥|zhi:之,乿,侄,俧,倁,値,值,偫,傂,儨,凪,制,劕,劧,卮,厔,只,吱,咫,址,坁,坧,垁,埴,執,墆,墌,夂,姪,娡,嬂,寘,峙,崻,巵,帋,帙,帜,幟,庢,庤,廌,彘,徏,徔,徝,志,忮,恉,慹,憄,懥,懫,戠,执,扺,扻,抧,挃,指,挚,掷,搘,搱,摭,摯,擲,擿,支,旘,旨,晊,智,枝,枳,柣,栀,栉,桎,梔,梽,植,椥,榰,槜,樴,櫍,櫛,止,殖,汁,汥,汦,沚,治,洔,洷,淽,滍,滞,滯,漐,潌,潪,瀄,炙,熫,狾,猘,瓆,瓡,畤,疐,疷,疻,痔,痣,瘈,直,知,砋,礩,祉,祑,祗,祬,禃,禔,禵,秓,秖,秩,秪,秲,秷,稙,稚,稺,穉,窒,筫,紙,紩,絷,綕,緻,縶,織,纸,织,置,翐,聀,聁,职,職,肢,胑,胝,脂,膣,膱,至,致,臸,芖,芝,芷,茋,藢,蘵,蛭,蜘,螲,蟙,衹,衼,袟,袠,製,襧,覟,觗,觯,觶,訨,誌,謢,豑,豒,豸,貭,質,贄,质,贽,趾,跖,跱,踬,踯,蹠,蹢,躑,躓,軄,軹,輊,轵,轾,郅,酯,釞,銍,鋕,鑕,铚,锧,阤,阯,陟,隲,隻,雉,馶,馽,駤,騭,騺,驇,骘,鯯,鳷,鴙,鴲,鷙,鸷,黹,鼅,㕄,㗌,㗧,㘉,㙷,㛿,㜼,㝂,㣥,㧻,㨁,㨖,㮹,㲛,㴛,䄺,䅩,䆈,䇛,䇽,䉅,䉜,䌤,䎺,䏄,䏯,䐈,䐭,䑇,䓌,䕌,䚦,䛗,䝷,䞃,䟈,䡹,䥍,䦯,䫕,䬹,䭁,䱥,䱨,䳅,䵂|zha:乍,偧,劄,厏,吒,咋,咤,哳,喳,奓,宱,扎,抯,挓,揸,搩,搾,摣,札,柤,柵,栅,楂,榨,樝,渣,溠,灹,炸,煠,牐,甴,痄,皶,皻,皼,眨,砟,箚,膪,苲,蚱,蚻,觰,詐,譇,譗,诈,踷,軋,轧,迊,醡,鍘,铡,閘,闸,霅,鮓,鮺,鲊,鲝,齄,齇,㒀,㡸,㱜,㴙,㷢,䋾,䕢,䖳,䛽,䞢,䥷,䵙,䵵|hu:乎,乕,互,冱,冴,匢,匫,呼,唬,唿,喖,嘑,嘝,嚛,囫,垀,壶,壷,壺,婟,媩,嫭,嫮,寣,岵,帍,幠,弖,弧,忽,怙,恗,惚,戶,户,戸,戽,扈,抇,护,搰,摢,斛,昈,昒,曶,枑,楜,槲,槴,歑,汻,沍,沪,泘,浒,淴,湖,滬,滸,滹,瀫,烀,焀,煳,熩,狐,猢,琥,瑚,瓠,瓳,祜,笏,箎,箶,簄,粐,糊,絗,綔,縠,胡,膴,芐,苸,萀,葫,蔛,蔰,虍,虎,虖,虝,蝴,螜,衚,觳,謼,護,軤,轷,鄠,醐,錿,鍙,鍸,雐,雽,韄,頀,頶,餬,鬍,魱,鯱,鰗,鱯,鳠,鳸,鶘,鶦,鶮,鸌,鹕,鹱,㕆,㗅,㦿,㨭,㪶,㫚,㯛,㸦,㹱,㺉,㾰,㿥,䁫,䇘,䈸,䉉,䉿,䊀,䍓,䎁,䔯,䕶,䗂,䚛,䛎,䞱,䠒,䧼,䨥,䨼,䩴,䪝,䭅,䭌,䭍,䮸,䲵|fa:乏,伐,佱,傠,发,垡,姂,彂,栰,橃,沷,法,灋,珐,琺,疺,発,發,瞂,砝,筏,罚,罰,罸,茷,藅,醗,鍅,閥,阀,髪,髮,㕹,㘺,㛲,䂲,䇅,䒥,䣹|le:乐,仂,勒,叻,忇,扐,楽,樂,氻,泐,玏,砳,竻,簕,艻,阞,韷,餎,饹,鰳,鳓,㔹,㖀,㦡|yin:乑,乚,侌,冘,凐,印,吟,吲,唫,喑,噖,噾,嚚,囙,因,圁,垔,垠,垽,堙,夤,姻,婣,婬,寅,尹,峾,崟,崯,嶾,廕,廴,引,愔,慇,慭,憖,憗,懚,斦,朄,栶,檃,檭,檼,櫽,歅,殥,殷,氤,泿,洇,洕,淫,淾,湚,溵,滛,濥,濦,烎,犾,狺,猌,珢,璌,瘖,瘾,癊,癮,碒,磤,禋,秵,筃,粌,絪,緸,胤,苂,茚,茵,荫,荶,蒑,蔩,蔭,蘟,蚓,螾,蟫,裀,訔,訚,訡,誾,諲,讔,趛,鄞,酳,釿,鈏,鈝,銀,銦,铟,银,闉,阥,阴,陰,陻,隂,隐,隠,隱,霒,霠,霪,靷,鞇,音,韾,飮,飲,饮,駰,骃,鮣,鷣,齗,齦,龂,龈,㐆,㕂,㖗,㙬,㝙,㞤,㡥,㣧,㥯,㥼,㦩,㧈,㪦,㱃,㴈,㸒,㹜,㹞,㼉,㾙,䇙,䌥,䒡,䓄,䕃,䖜,䚿,䡛,䤃,䤺,䨸,䪩,䲟|ping:乒,俜,凭,凴,呯,坪,塀,娦,屏,屛,岼,帡,帲,幈,平,慿,憑,枰,檘,洴,涄,淜,焩,玶,瓶,甁,甹,砯,竮,箳,簈,缾,聠,艵,苹,荓,萍,蓱,蘋,蚲,蛢,評,评,軿,輧,郱,頩,鮃,鲆,㺸,㻂,䍈,䶄|pang:乓,厐,嗙,嫎,庞,旁,汸,沗,滂,炐,篣,耪,肨,胖,胮,膖,舽,螃,蠭,覫,逄,雱,霶,髈,鰟,鳑,龎,龐,㜊,㤶,㥬,㫄,䅭,䒍,䨦,䮾|qiao:乔,侨,俏,僑,僺,劁,喬,嘺,墝,墽,嫶,峭,嵪,巧,帩,幧,悄,愀,憔,撬,撽,敲,桥,槗,樵,橇,橋,殼,燆,犞,癄,睄,瞧,硗,硚,碻,磽,礄,窍,竅,繑,繰,缲,翘,翹,荍,荞,菬,蕎,藮,誚,譙,诮,谯,趫,趬,跷,踍,蹺,蹻,躈,郻,鄗,鄡,鄥,釥,鍫,鍬,鐈,鐰,锹,陗,鞒,鞘,鞩,鞽,韒,頝,顦,骹,髚,髜,㚁,㚽,㝯,㡑,㢗,㤍,㪣,㴥,䀉,䃝,䆻,䇌,䎗,䩌,䱁,䲾|guai:乖,叏,夬,怪,恠,拐,枴,柺,箉,㧔,㷇,㽇,䂯,䊽|mie:乜,吀,咩,哶,孭,幭,懱,搣,櫗,滅,瀎,灭,瓱,篾,蔑,薎,蠛,衊,覕,鑖,鱴,鴓,㒝,䁾,䈼,䘊,䩏|xi:习,係,俙,傒,僖,兮,凞,匸,卌,卥,厀,吸,呬,咥,唏,唽,喜,嘻,噏,嚱,塈,壐,夕,奚,娭,媳,嬆,嬉,屃,屖,屗,屣,嵠,嶍,巇,希,席,徆,徙,徚,徯,忚,忥,怬,怸,恄,息,悉,悕,惁,惜,慀,憘,憙,戏,戯,戱,戲,扸,昔,晞,晰,晳,暿,曦,杫,析,枲,桸,椞,椺,榽,槢,樨,橀,橲,檄,欯,欷,歖,歙,歚,氥,汐,洗,浠,淅,渓,溪,滊,漇,漝,潝,潟,澙,烯,焁,焈,焟,焬,煕,熂,熄,熈,熙,熹,熺,熻,燨,爔,牺,犀,犔,犠,犧,狶,玺,琋,璽,瘜,皙,盻,睎,瞦,矖,矽,硒,磶,礂,禊,禧,稀,稧,穸,窸,粞,系,細,綌,緆,縰,繥,纚,细,绤,羲,習,翕,翖,肸,肹,膝,舄,舾,莃,菥,葈,葸,蒠,蒵,蓆,蓰,蕮,薂,虩,蜥,蝷,螅,螇,蟋,蟢,蠵,衋,袭,襲,西,覀,覡,覤,觋,觹,觽,觿,誒,諰,謑,謵,譆,诶,谿,豀,豨,豯,貕,赥,赩,趇,趘,蹝,躧,郄,郋,郗,郤,鄎,酅,醯,釳,釸,鈢,銑,錫,鎴,鏭,鑴,铣,锡,闟,阋,隙,隟,隰,隵,雟,霫,霼,飁,餏,餙,餼,饩,饻,騱,騽,驨,鬩,鯑,鰼,鱚,鳛,鵗,鸂,黖,鼷,㑶,㔒,㗩,㙾,㚛,㞒,㠄,㣟,㤴,㤸,㥡,㦻,㩗,㭡,㳧,㵿,㸍,㹫,㽯,㿇,䀘,䂀,䈪,䊠,䏮,䐼,䓇,䙽,䚷,䛥,䜁,䢄,䧍,䨳,䩤,䫣,䮎,䲪|xiang:乡,享,亯,佭,像,勨,厢,向,响,啌,嚮,姠,嶑,巷,庠,廂,忀,想,晑,曏,栙,楿,橡,欀,湘,珦,瓖,瓨,相,祥,箱,絴,緗,缃,缿,翔,膷,芗,萫,葙,薌,蚃,蟓,蠁,襄,襐,詳,详,象,跭,郷,鄉,鄊,鄕,銄,鐌,鑲,镶,響,項,项,飨,餉,饗,饟,饷,香,驤,骧,鮝,鯗,鱌,鱜,鱶,鲞,麘,㐮,㗽,㟄,㟟,䊑,䐟,䔗,䖮,䜶,䢽|hai:乤,亥,咍,嗐,嗨,嚡,塰,孩,害,氦,海,烸,胲,酼,醢,餀,饚,駭,駴,骇,骸,㜾,㤥,㦟,㧡,㨟,㺔,䇋,䠽,䯐,䱺|shu:书,侸,倏,倐,儵,叔,咰,塾,墅,姝,婌,孰,尌,尗,属,庶,庻,怷,恕,戍,抒,掓,摅,攄,数,數,暏,暑,曙,書,朮,术,束,杸,枢,柕,树,梳,樞,樹,橾,殊,殳,毹,毺,沭,淑,漱,潄,潻,澍,濖,瀭,焂,熟,瑹,璹,疎,疏,癙,秫,竖,竪,籔,糬,紓,絉,綀,纾,署,腧,舒,荗,菽,蒁,蔬,薥,薯,藷,虪,蜀,蠴,術,裋,襡,襩,豎,贖,赎,跾,踈,軗,輸,输,述,鄃,鉥,錰,鏣,陎,鮛,鱪,鱰,鵨,鶐,鶑,鸀,黍,鼠,鼡,㒔,㛸,㜐,㟬,㣽,㯮,㳆,㶖,㷂,㻿,㽰,㾁,䃞,䆝,䉀,䎉,䘤,䜹,䝂,䝪,䞖,䠱,䢤,䩱,䩳,䴰|dou:乧,兜,兠,剅,吺,唗,抖,斗,斣,枓,梪,橷,毭,浢,痘,窦,竇,篼,脰,艔,荳,蔸,蚪,豆,逗,郖,酘,鈄,鋀,钭,閗,闘,阧,陡,餖,饾,鬥,鬦,鬪,鬬,鬭,㛒,㞳,㢄,㨮,㪷,㷆,䄈,䕆,䕱,䛠,䬦|nang:乪,儾,嚢,囊,囔,擃,攮,曩,欜,灢,蠰,饢,馕,鬞,齉,㒄,㶞,䂇|kai:乫,凯,凱,剀,剴,勓,嘅,垲,塏,奒,开,忾,恺,愷,愾,慨,揩,暟,楷,欬,炌,炏,烗,蒈,衉,輆,鍇,鎎,鎧,鐦,铠,锎,锴,開,闓,闿,颽,㡁,㲉,䁗,䐩,䒓,䡷|keng:乬,劥,厼,吭,唟,坈,坑,巪,怾,挳,牼,硁,硜,硻,誙,銵,鍞,鏗,铿,䡰|ting:乭,亭,侹,停,厅,厛,听,圢,娗,婷,嵉,庁,庭,廰,廳,廷,挺,桯,梃,楟,榳,汀,涏,渟,濎,烃,烴,烶,珽,町,筳,綎,耓,聤,聴,聼,聽,脡,艇,艈,艼,莛,葶,蜓,蝏,誔,諪,邒,鋌,铤,閮,霆,鞓,頲,颋,鼮,㹶,䋼,䗴,䦐,䱓,䵺|mo:乮,劘,劰,嗼,嚤,嚩,圽,塻,墨,妺,嫫,嫼,寞,尛,帓,帞,怽,懡,抹,摩,摸,摹,擵,昩,暯,末,枺,模,橅,歾,歿,殁,沫,漠,爅,瘼,皌,眜,眽,眿,瞐,瞙,砞,磨,礳,秣,粖,糢,絈,縸,纆,耱,膜,茉,莈,莫,蓦,藦,蘑,蛨,蟔,袹,謨,謩,譕,谟,貃,貊,貘,銆,鏌,镆,陌,靺,饃,饝,馍,驀,髍,魔,魩,魹,麼,麽,麿,默,黙,㱄,㱳,㷬,㷵,㹮,䁼,䁿,䃺,䉑,䏞,䒬,䘃,䜆,䩋,䬴,䮬,䯢,䱅,䳮,䴲|ou:乯,偶,吘,呕,嘔,噢,塸,夞,怄,慪,櫙,欧,歐,殴,毆,毮,沤,漚,熰,瓯,甌,筽,耦,腢,膒,蕅,藕,藲,謳,讴,鏂,鞰,鴎,鷗,鸥,齵,㒖,㛏,㼴,䌂,䌔,䚆,䯚|mai:买,佅,劢,勱,卖,嘪,埋,売,脈,脉,荬,蕒,薶,衇,買,賣,迈,邁,霡,霢,霾,鷶,麥,麦,㜥,㼮,䁲,䈿,䘑,䚑,䜕,䨪,䨫,䮮|luan:乱,亂,卵,圝,圞,奱,孌,孪,孿,峦,巒,挛,攣,曫,栾,欒,滦,灓,灤,癴,癵,羉,脔,臠,虊,釠,銮,鑾,鵉,鸞,鸾,㝈,㡩,㱍,䖂,䜌|cai:乲,倸,偲,埰,婇,寀,彩,戝,才,採,材,棌,猜,睬,綵,縩,纔,菜,蔡,裁,財,财,跴,踩,采,㒲,㥒,䌨,䌽,䐆,䣋,䰂,䴭|ru:乳,侞,儒,入,嗕,嚅,如,媷,嬬,孺,嶿,帤,扖,擩,曘,杁,桇,汝,洳,渪,溽,濡,燸,筎,縟,繻,缛,肗,茹,蒘,蓐,蕠,薷,蠕,袽,褥,襦,辱,込,邚,鄏,醹,銣,铷,顬,颥,鱬,鳰,鴑,鴽,㦺,㨎,㹘,䋈,䰰|xue:乴,吷,坹,学,學,岤,峃,嶨,怴,斈,桖,樰,泧,泶,澩,瀥,烕,燢,狘,疦,疶,穴,膤,艝,茓,蒆,薛,血,袕,觷,謔,谑,趐,踅,轌,辥,雤,雪,靴,鞾,鱈,鳕,鷽,鸴,㖸,㞽,㡜,㧒,㶅,㿱,䎀,䤕,䨮,䫻,䫼,䬂,䭥,䱑|peng:乶,倗,傰,剻,匉,喸,嘭,堋,塜,塳,巼,弸,彭,怦,恲,憉,抨,挷,捧,掽,搒,朋,梈,棚,椖,椪,槰,樥,泙,浌,淎,漨,漰,澎,烹,熢,皏,砰,硑,硼,碰,磞,稝,竼,篷,纄,胓,膨,芃,莑,蓬,蟚,蟛,踫,軯,輣,錋,鑝,閛,闏,韸,韼,駍,騯,髼,鬅,鬔,鵬,鹏,㛔,㥊,㼞,䄘,䡫,䰃,䴶|sha:乷,倽,傻,儍,刹,唦,唼,啥,喢,帹,挱,杀,榝,樧,歃,殺,沙,煞,猀,痧,砂,硰,箑,粆,紗,繌,繺,纱,翜,翣,莎,萐,蔱,裟,鎩,铩,閯,閷,霎,魦,鯊,鯋,鲨,㚫,㛼,㰱,䈉,䝊,䮜,䵘,䶎|na:乸,吶,呐,哪,嗱,妠,娜,拏,拿,挐,捺,笝,納,纳,肭,蒳,衲,袦,誽,豽,貀,軜,那,鈉,鎿,钠,镎,雫,靹,魶,㗙,㨥,㴸,䀑,䅞,䇣,䇱,䈫,䎎,䏧,䖓,䖧,䛔,䟜,䪏,䫱,䱹|qian:乹,乾,仟,仱,伣,佥,俔,倩,偂,傔,僉,儙,凵,刋,前,千,嗛,圱,圲,堑,塹,墘,壍,奷,婜,媊,嬱,孯,岍,岒,嵌,嵰,忴,悓,悭,愆,慊,慳,扦,扲,拑,拪,掔,掮,揵,搴,摼,撁,攐,攑,攓,杄,棈,椠,榩,槏,槧,橬,檶,櫏,欠,欦,歉,歬,汘,汧,浅,淺,潛,潜,濳,灊,牵,牽,皘,竏,签,箝,箞,篏,篟,簽,籖,籤,粁,綪,縴,繾,缱,羬,肷,膁,臤,芊,芡,茜,茾,荨,蒨,蔳,蕁,虔,蚈,蜸,褰,諐,謙,譴,谦,谴,谸,軡,輤,迁,遣,遷,釺,鈆,鈐,鉆,鉗,鉛,銭,錢,鎆,鏲,鐱,鑓,钎,钤,钱,钳,铅,阡,雃,韆,顅,騚,騝,騫,骞,鬜,鬝,鰬,鵮,鹐,黔,黚,㐸,㜞,㟻,㡨,㦮,㧄,㨜,㩮,㯠,㸫,䁮,䈤,䈴,䊴,䍉,䖍,䥅,䦲,䨿,䪈,䫡,䭤|er:乻,二,仒,佴,侕,儿,児,兒,刵,咡,唲,尒,尓,尔,峏,弍,弐,旕,栭,栮,樲,毦,洏,洱,爾,珥,粫,而,耏,耳,聏,胹,荋,薾,衈,袻,誀,貮,貳,贰,趰,輀,轜,迩,邇,鉺,铒,陑,隭,餌,饵,駬,髵,鮞,鲕,鴯,鸸,㒃,㖇,㚷,㛅,㜨,㢽,㧫,㮕,䋙,䋩,䌺,䎟,䎠,䎶,䏪,䣵,䮘|cui:乼,伜,倅,催,凗,啐,啛,墔,崔,嶉,忰,悴,慛,摧,榱,槯,毳,淬,漼,焠,獕,璀,疩,瘁,皠,磪,竁,粹,紣,綷,縗,缞,翆,翠,脃,脆,膬,膵,臎,萃,襊,趡,鏙,顇,㝮,㥞,㧘,㯔,㯜,㱖,㳃,㵏,㷃,㷪,䂱,䃀,䄟,䆊,䊫,䧽|ceng:乽,噌,层,層,岾,嶒,猠,硛,硳,竲,蹭,驓,㣒,㬝,䁬,䉕|gui:亀,佹,刽,刿,劊,劌,匦,匭,厬,圭,垝,妫,姽,媯,嫢,嬀,宄,嶲,巂,帰,庋,庪,归,恑,摫,撌,攰,攱,昋,晷,柜,桂,椝,椢,槶,槻,槼,櫃,櫷,歸,氿,湀,溎,炅,珪,瑰,璝,瓌,癸,皈,瞆,瞡,瞶,硅,祪,禬,窐,筀,簂,簋,胿,膭,茥,蓕,蛫,蟡,袿,襘,規,规,觤,詭,诡,貴,贵,跪,軌,轨,邽,郌,閨,闺,陒,鞼,騩,鬶,鬹,鬼,鮭,鱖,鱥,鲑,鳜,龜,龟,㔳,㙺,㧪,㨳,㩻,㪈,㲹,㸵,䁛,䇈,䌆,䍯,䍷,䐴,䖯,䙆,䝿,䞈,䞨,䠩,䣀,䤥,䯣,䰎,䳏|gan:亁,仠,倝,凎,凲,坩,尲,尴,尶,尷,干,幹,忓,感,擀,攼,敢,旰,杆,柑,桿,榦,橄,檊,汵,泔,淦,漧,澉,灨,玕,甘,疳,皯,盰,矸,秆,稈,竿,笴,筸,簳,粓,紺,绀,肝,芉,苷,衦,詌,贛,赣,赶,趕,迀,酐,骭,魐,鱤,鳡,鳱,㺂,䃭,䇞,䔈,䤗,䯎,䲺,䵟|jue:亅,倔,傕,决,刔,劂,勪,厥,噘,噱,妜,孒,孓,屩,屫,崛,嶡,嶥,彏,憠,憰,戄,抉,挗,捔,掘,撅,撧,攫,斍,桷,橛,橜,欔,欮,殌,氒,決,泬,潏,灍,焆,熦,爑,爝,爴,爵,獗,玃,玦,玨,珏,瑴,瘚,矍,矡,砄,絕,絶,绝,臄,芵,蕝,蕨,虳,蚗,蟨,蟩,覐,覚,覺,觉,觖,觼,訣,譎,诀,谲,貜,赽,趉,趹,蹶,蹷,躩,逫,鈌,鐍,鐝,钁,镢,镼,駃,鴂,鴃,鶌,鷢,龣,㓸,㔃,㔢,㟲,㤜,㩱,㭈,㭾,㰐,㵐,㷾,㸕,㹟,㻕,䀗,䁷,䆕,䆢,䇶,䋉,䍊,䏐,䏣,䐘,䖼,䘿,䙠,䝌,䞵,䞷,䟾,䠇,䡈,䦆,䦼|liao:了,僚,嘹,嫽,寥,寮,尞,尥,尦,屪,嵺,嶚,嶛,廖,廫,憀,憭,撂,撩,敹,料,暸,漻,潦,炓,燎,爎,爒,獠,璙,疗,療,瞭,窷,竂,簝,繚,缭,聊,膋,膫,蓼,蟟,豂,賿,蹘,蹽,辽,遼,鄝,釕,鐐,钌,镣,镽,飉,髎,鷯,鹩,㙩,㝋,㡻,㵳,㶫,㺒,䄦,䉼,䍡,䎆,䑠,䜍,䜮,䝀,䢧,䨅,䩍|ma:亇,傌,吗,唛,嗎,嘛,嘜,妈,媽,嫲,嬤,嬷,杩,榪,溤,犘,犸,獁,玛,瑪,痲,睰,码,碼,礣,祃,禡,罵,蔴,蚂,螞,蟆,蟇,遤,鎷,閁,馬,駡,马,骂,鬕,鰢,鷌,麻,㐷,㑻,㜫,㦄,㨸,㾺,䗫,䣕,䣖,䯦,䳸|zheng:争,佂,凧,埩,塣,姃,媜,峥,崝,崢,帧,幀,征,徰,徴,徵,怔,愸,抍,拯,挣,掙,掟,揁,撜,政,整,晸,正,氶,炡,烝,爭,狰,猙,症,癥,眐,睁,睜,筝,箏,篜,糽,聇,蒸,証,諍,證,证,诤,踭,郑,鄭,鉦,錚,钲,铮,鬇,鴊,㡠,㡧,㱏,㽀,䂻,䈣,䛫,䡕,䥌,䥭,䦛,䦶|chu:亍,俶,傗,储,儊,儲,処,出,刍,初,厨,嘼,埱,处,岀,幮,廚,怵,憷,懨,拀,搋,搐,摴,敊,斶,杵,椘,楚,楮,榋,樗,橱,橻,檚,櫉,櫥,欪,歜,滀,滁,濋,犓,珿,琡,璴,矗,础,礎,禇,竌,竐,篨,絀,绌,耡,臅,芻,蒢,蒭,蕏,處,蜍,蟵,褚,触,觸,諔,豖,豠,貙,趎,踀,蹰,躇,躕,鄐,鉏,鋤,锄,閦,除,雏,雛,鶵,黜,齣,齭,齼,㔘,㕏,㕑,㗰,㙇,㡡,㤕,㤘,㶆,㹼,㼥,䅳,䊰,䎝,䎤,䖏,䙕,䙘,䜴,䟞,䟣,䠂,䠧,䦌,䧁,䮞|kui:亏,傀,刲,匮,匱,卼,喟,喹,嘳,夔,奎,媿,嬇,尯,岿,巋,巙,悝,愦,愧,憒,戣,揆,晆,暌,楏,楑,樻,櫆,欳,殨,溃,潰,煃,盔,睽,磈,窥,窺,篑,簣,籄,聧,聩,聭,聵,葵,蒉,蒊,蕢,藈,蘬,蘷,虁,虧,蝰,謉,跬,蹞,躨,逵,鄈,鍨,鍷,鐀,鑎,闚,頄,頍,頯,顝,餽,饋,馈,馗,騤,骙,魁,㕟,㙓,㚝,㛻,㨒,䈐,䍪,䕚,䕫,䟸,䠑,䤆,䦱,䧶,䫥,䯓,䳫|yun:云,伝,傊,允,勻,匀,呍,喗,囩,夽,奫,妘,孕,恽,惲,愠,愪,慍,抎,抣,昀,晕,暈,枟,橒,殒,殞,氲,氳,沄,涢,溳,澐,煴,熅,熉,熨,狁,玧,畇,眃,磒,秐,筼,篔,紜,緼,縕,縜,繧,纭,缊,耘,耺,腪,芸,荺,蒀,蒕,蒷,蕓,蕰,蕴,薀,藴,蘊,蝹,褞,賱,贇,赟,运,運,郓,郧,鄆,鄖,酝,醖,醞,鈗,鋆,阭,陨,隕,雲,霣,韗,韞,韫,韵,韻,頵,餫,馧,馻,齫,齳,㚃,㚺,㜏,㞌,㟦,䆬,䇖,䉙,䚋,䞫,䡝,䢵,䤞,䦾,䨶,䩵,䪳,䲰,䵴|sui:亗,倠,哸,埣,夊,嬘,岁,嵗,旞,檖,歲,歳,浽,滖,澻,濉,瀡,煫,熣,燧,璲,瓍,眭,睟,睢,砕,碎,祟,禭,穂,穗,穟,粋,綏,繀,繐,繸,绥,脺,膸,芕,荽,荾,葰,虽,襚,誶,譢,谇,賥,遀,遂,邃,鐆,鐩,隋,随,隧,隨,雖,鞖,髄,髓,㒸,㞸,㴚,㵦,㻟,㻪,㻽,䅗,䉌,䍁,䔹,䜔,䠔,䡵,䢫,䥙,䭉,䯝|gen:亘,哏,揯,搄,根,艮,茛,跟,㫔,㮓,䫀|geng:亙,刯,哽,啹,喼,嗰,埂,堩,峺,庚,挭,掶,更,梗,椩,浭,焿,畊,絚,綆,緪,縆,绠,羮,羹,耕,耿,莄,菮,賡,赓,郠,骾,鯁,鲠,鶊,鹒,㾘,䋁,䌄,䱍,䱎,䱭,䱴|xie:些,亵,伳,偕,偰,僁,写,冩,劦,勰,协,協,卨,卸,嗋,噧,垥,塮,夑,奊,娎,媟,寫,屑,屓,屟,屧,屭,峫,嶰,廨,徢,恊,愶,懈,拹,挟,挾,揳,携,撷,擕,擷,攜,斜,旪,暬,械,楔,榍,榭,歇,泄,泻,洩,渫,澥,瀉,瀣,灺,炧,炨,焎,熁,燮,燲,爕,猲,獬,瑎,祄,禼,糏,紲,絏,絜,絬,綊,緤,緳,纈,绁,缬,缷,翓,胁,脅,脇,脋,膎,薢,薤,藛,蝎,蝢,蟹,蠍,蠏,衺,褉,褻,襭,諧,謝,讗,谐,谢,躞,躠,邂,邪,鐷,鞋,鞢,鞵,韰,齂,齘,齥,龤,㒠,㓔,㔎,㕐,㖑,㖿,㙝,㙰,㝍,㞕,㣯,㣰,㥟,㦪,㨙,㨝,㩉,㩦,㩪,㭨,㰔,㰡,㳦,㳿,㴬,㴮,㴽,㸉,㽊,䉏,䉣,䊝,䔑,䕈,䕵,䙊,䙎,䙝,䚳,䚸,䡡,䢡,䥱,䥾,䦏,䦑,䩧,䭎,䲒,䵦|tou:亠,偷,偸,头,妵,婾,媮,投,敨,斢,殕,紏,緰,蘣,透,鍮,頭,骰,黈,㓱,㖣,㡏,㢏,㪗,䞬,䟝,䱏,䵉|wang:亡,亾,仼,兦,妄,尣,尩,尪,尫,彺,往,徃,忘,忹,惘,旺,暀,望,朢,枉,棢,汪,瀇,焹,王,盳,網,网,罔,莣,菵,蚟,蛧,蝄,誷,輞,辋,迋,魍,㑌,㓁,㲿,㳹,㴏,䋄,䋞,䛃,䤑,䰣|kang:亢,伉,匟,囥,嫝,嵻,康,忼,慷,扛,抗,摃,槺,漮,炕,犺,砊,穅,粇,糠,躿,邟,鈧,鏮,钪,閌,闶,鱇,㰠,䡉|da:亣,剳,匒,呾,咑,哒,嗒,噠,垯,墶,大,妲,怛,打,搭,撘,橽,沓,溚,炟,燵,畣,瘩,眔,笪,答,繨,羍,耷,荅,荙,薘,蟽,褡,詚,跶,躂,达,迏,迖,逹,達,鎉,鎝,鐽,靼,鞑,韃,龖,龘,㙮,㜓,㟷,㯚,㾑,㿯,䃮,䐊,䑽,䩢,䳴,䵣|jiao:交,佼,侥,僥,僬,儌,剿,劋,勦,叫,呌,嘂,嘄,嘦,噍,噭,嚼,姣,娇,嬌,嬓,孂,峤,峧,嶕,嶠,嶣,徼,憍,挍,挢,捁,搅,摷,撟,撹,攪,敎,教,敫,敽,敿,斠,晈,暞,曒,椒,櫵,浇,湫,湬,滘,漖,潐,澆,灚,烄,焦,焳,煍,燋,狡,獥,珓,璬,皎,皦,皭,矫,矯,礁,穚,窌,窖,笅,筊,簥,絞,繳,纐,绞,缴,胶,脚,腳,膠,膲,臫,艽,芁,茭,茮,蕉,藠,虠,蛟,蟜,蟭,角,訆,譑,譥,賋,趭,跤,踋,較,轇,轎,轿,较,郊,酵,醮,釂,鉸,鐎,铰,餃,饺,驕,骄,鮫,鱎,鲛,鵁,鵤,鷦,鷮,鹪,㠐,㩰,㬭,㭂,㰾,㳅,㽱,㽲,䀊,䁶,䂃,䆗,䘨,䚩,䠛,䣤,䥞,䪒,䴔,䴛|heng:亨,哼,啈,囍,堼,姮,恆,恒,悙,桁,横,橫,涥,烆,珩,胻,脝,蘅,衡,鑅,鴴,鵆,鸻,㔰,㶇,䄓,䒛,䬖,䬝,䯒|qin:亲,侵,勤,吢,吣,唚,嗪,噙,坅,埁,媇,嫀,寑,寝,寢,寴,嵚,嶔,庈,懃,懄,抋,捦,揿,搇,撳,擒,斳,昑,梫,檎,欽,沁,溱,澿,瀙,珡,琴,琹,瘽,矝,禽,秦,笉,綅,耹,芩,芹,菣,菦,菳,藽,蚙,螓,螼,蠄,衾,親,誛,赺,赾,鈙,鋟,钦,锓,雂,靲,顉,駸,骎,鮼,鳹,㝲,㞬,㢙,㤈,㩒,㪁,㮗,㾛,䈜,䔷,䖌,䠴,䦦|bo:亳,仢,伯,侼,僠,僰,勃,博,卜,啵,嚗,壆,孛,孹,嶓,帛,愽,懪,拨,挬,捕,搏,撥,播,擘,柭,桲,檗,欂,泊,波,浡,淿,渤,湐,煿,牔,犦,犻,狛,猼,玻,瓝,瓟,癶,癷,盋,砵,碆,磻,礡,礴,秡,箔,箥,簙,簸,糪,紴,缽,胉,脖,膊,舶,艊,苩,菠,葧,蔔,蘗,蚾,袚,袯,袰,襏,襮,譒,豰,跛,踣,蹳,郣,鈸,鉑,鉢,鋍,鎛,鑮,钵,钹,铂,镈,餑,餺,饽,馎,馛,馞,駁,駮,驋,驳,髆,髉,鮊,鱍,鲌,鵓,鹁,㖕,㗘,㝿,㟑,㧳,㩧,㩭,㪍,㬍,㬧,㱟,㴾,㶿,㹀,䂍,䊿,䍨,䍸,䑈,䒄,䗚,䙏,䞳,䟛,䢌,䥬,䪇,䪬,䫊,䬪,䭦,䭯,䮀,䮂,䯋,䰊,䶈|lian:亷,僆,劆,匲,匳,嗹,噒,堜,奁,奩,娈,媡,嫾,嬚,帘,廉,怜,恋,慩,憐,戀,摙,敛,斂,梿,楝,槤,櫣,歛,殓,殮,浰,涟,湅,溓,漣,潋,澰,濂,濓,瀲,炼,煉,熑,燫,琏,瑓,璉,磏,稴,簾,籢,籨,練,縺,纞,练,羷,翴,联,聨,聫,聮,聯,脸,臁,臉,莲,萰,蓮,蔹,薕,蘝,蘞,螊,蠊,裢,裣,褳,襝,覝,謰,譧,蹥,连,連,鄻,錬,鍊,鎌,鏈,鐮,链,镰,鬑,鰊,鰱,鲢,㓎,㜃,㜕,㜻,㝺,㟀,㡘,㢘,㥕,㦁,㦑,㪘,㪝,㯬,㰈,㰸,㱨,㶌,㶑,㺦,㼑,㼓,㾾,䁠,䃛,䆂,䇜,䌞,䏈,䙺,䥥,䨬,䭑|duo:亸,仛,凙,刴,剁,剟,剫,咄,哆,哚,喥,嚉,嚲,垛,垜,埵,堕,墮,墯,多,夛,夺,奪,尮,崜,嶞,惰,憜,挅,挆,掇,敓,敚,敠,敪,朵,朶,柮,桗,椯,毲,沲,痥,綞,缍,舵,茤,裰,趓,跢,跥,跺,踱,躱,躲,軃,鈬,鐸,铎,陊,陏,飿,饳,鬌,鮵,鵽,㔍,㖼,㙐,㛆,㛊,㣞,㥩,㧷,㻔,㻧,䅜,䍴,䐾,䑨,䒳,䙃,䙟,䙤,䠤,䤪,䤻,䩔,䩣,䫂,䯬|ren:人,亻,仁,仞,仭,任,刃,刄,壬,妊,姙,屻,忈,忍,忎,恁,扨,朲,杒,栠,栣,梕,棯,牣,秂,秹,稔,紉,紝,絍,綛,纫,纴,肕,腍,芢,荏,荵,葚,衽,袵,訒,認,认,讱,躵,軔,轫,鈓,銋,靭,靱,韌,韧,飪,餁,饪,魜,鵀,㠴,㣼,㶵,㸾,䀼,䇮,䋕,䌾,䏕,䏰,䭃,䴦|ra:亽,囕,罖|ze:仄,伬,则,則,唶,啧,啫,嘖,夨,嫧,崱,帻,幘,庂,択,择,捑,擇,昃,昗,樍,歵,汄,沢,泎,泽,溭,澤,皟,瞔,矠,礋,稄,笮,箦,簀,耫,舴,蔶,蠌,襗,諎,謮,責,賾,责,赜,迮,鸅,齚,齰,㖽,㣱,㳁,㳻,䃎,䇥,䕉,䕪,䰹,䶦|jin:仅,今,伒,侭,僅,僸,儘,兓,凚,劤,劲,勁,卺,厪,噤,嚍,埐,堇,堻,墐,壗,妗,嫤,嬧,寖,尽,嶜,巹,巾,廑,惍,慬,搢,斤,晉,晋,枃,槿,歏,殣,津,浕,浸,溍,漌,濅,濜,烬,煡,燼,珒,琎,琻,瑨,瑾,璡,璶,盡,矜,砛,祲,禁,筋,紟,紧,緊,縉,缙,荕,荩,菫,蓳,藎,衿,襟,覲,觐,觔,謹,谨,賮,贐,赆,近,进,進,金,釒,錦,钅,锦,靳,饉,馑,鹶,黅,齽,㝻,㨷,㬐,㬜,㯲,㯸,㰹,㱈,㴆,㶦,㶳,㹏,䀆,䆮,䋮,䌝,䐶,䑤,䒺,䖐,䗯,䝲,䤐,䥆,䫴,䭙,䶖|pu:仆,僕,匍,噗,圃,圑,圤,埔,墣,巬,巭,扑,抪,撲,擈,攴,攵,普,暜,曝,朴,柨,樸,檏,氆,浦,溥,潽,濮,瀑,炇,烳,璞,痡,瞨,穙,纀,舖,舗,莆,菐,菩,葡,蒱,蒲,諩,譜,谱,贌,蹼,酺,鋪,鏷,鐠,铺,镤,镨,陠,駇,鯆,㒒,㬥,㯷,㲫,㹒,㺪,䈬,䈻,䑑,䔕,䗱,䧤,䲕,䴆|ba:仈,八,叐,叭,吧,哵,坝,坺,垻,墢,壩,夿,妭,岜,巴,弝,扒,把,抜,拔,捌,朳,欛,灞,炦,爸,犮,玐,疤,癹,矲,笆,粑,紦,罢,罷,羓,耙,胈,芭,茇,菝,蚆,覇,詙,豝,跁,跋,軷,釛,釟,鈀,钯,霸,靶,颰,魃,魞,鮁,鲃,鲅,鼥,㔜,㖠,㞎,㧊,㶚,䃻,䆉,䇑,䎬,䟦,䥯,䩗,䩻,䰾,䱝,䳁,䳊|reng:仍,扔,礽,芿,辸,陾,㭁,㺱,䄧,䚮|fo:仏,佛,坲,梻|tao:仐,匋,咷,啕,夲,套,嫍,幍,弢,慆,掏,搯,桃,梼,槄,檮,洮,涛,淘,滔,濤,瑫,畓,祹,絛,綯,縚,縧,绦,绹,萄,蜪,裪,討,詜,謟,讨,迯,逃,醄,鋾,錭,陶,鞀,鞉,鞱,韜,韬,飸,饀,饕,駣,騊,鼗,㚐,㹗,䚯,䚵,䬞,䵚|lun:仑,伦,侖,倫,囵,圇,埨,婨,崘,崙,惀,抡,掄,棆,沦,淪,溣,碖,磮,稐,綸,纶,耣,腀,菕,蜦,論,论,踚,輪,轮,錀,陯,鯩,㖮,㷍,䈁,䑳|cang:仓,仺,伧,倉,傖,凔,匨,嵢,欌,沧,滄,濸,獊,罉,舱,艙,苍,蒼,蔵,藏,螥,賶,鑶,鶬,鸧,㵴,㶓,䅮,䢢|zi:仔,倳,兹,剚,吇,呰,咨,唨,啙,嗞,姉,姊,姕,姿,子,孖,字,孜,孳,孶,崰,嵫,恣,杍,栥,梓,椔,榟,橴,淄,渍,湽,滋,滓,漬,澬,牸,玆,眥,眦,矷,禌,秄,秭,秶,稵,笫,籽,粢,紎,紫,緇,缁,耔,胏,胔,胾,自,芓,茊,茡,茲,葘,虸,觜,訾,訿,諮,谘,貲,資,赀,资,赼,趑,趦,輜,輺,辎,鄑,釨,鈭,錙,鍿,鎡,锱,镃,頾,頿,髭,鯔,鰦,鲻,鶅,鼒,齍,齜,龇,㜽,㧗,㰣,㰷,㱴,㺭,䅆,䐉,䔂,䘣|ta:他,侤,咜,嚃,嚺,塌,塔,墖,她,它,崉,挞,搨,撻,榙,榻,毾,涾,溻,澾,濌,牠,狧,獭,獺,祂,禢,褟,襨,誻,譶,趿,踏,蹋,蹹,躢,遝,遢,鉈,錔,铊,闒,闥,闼,阘,鞜,鞳,鮙,鰨,鳎,㒓,㗳,㛥,㣛,㣵,㧺,㭼,㯓,㳠,㳫,㹺,㺚,㿹,䂿,䈋,䈳,䌈,䍇,䍝,䎓,䑜,䓠,䜚,䵬,䶀,䶁|xian:仙,仚,伭,佡,僊,僩,僲,僴,先,冼,县,咞,咸,哯,唌,啣,嘕,垷,奾,妶,姭,娊,娨,娴,娹,婱,嫌,嫺,嫻,嬐,孅,宪,尟,尠,屳,岘,峴,崄,嶮,幰,廯,弦,忺,憪,憲,憸,挦,掀,搟,撊,撏,攇,攕,显,晛,暹,杴,枮,橌,櫶,毨,氙,涀,涎,湺,澖,瀗,灦,烍,燹,狝,猃,献,獫,獮,獻,玁,现,珗,現,甉,痫,癇,癎,県,睍,硍,礥,祆,禒,秈,筅,箲,籼,粯,糮,絃,絤,綫,線,縣,繊,纎,纖,纤,线,缐,羡,羨,胘,腺,臔,臽,舷,苋,苮,莧,莶,薟,藓,藔,藖,蘚,蚬,蚿,蛝,蜆,衔,衘,褼,襳,誢,誸,諴,譣,豏,賢,贒,贤,赻,跣,跹,蹮,躚,輱,酰,醎,銛,銜,鋧,錎,鍁,鍂,鍌,鏾,鑦,铦,锨,閑,闲,限,陥,险,陷,険,險,霰,韅,韯,韱,顕,顯,餡,馅,馦,鮮,鱻,鲜,鶱,鷳,鷴,鷼,鹇,鹹,麲,鼸,㔵,㘅,㘋,㛾,㜪,㡉,㡾,㢺,㦓,㧋,㧥,㩈,㪇,㫫,㬎,㬗,㭠,㭹,㮭,㯀,㳄,㳭,㵪,㶍,㺌,㿅,䀏,䁂,䃱,䃸,䉯,䉳,䏹,䒸,䕔,䗾,䘆,䚚,䜢,䝨,䞁,䢾,䤼,䥪,䦥,䧋,䧟,䧮,䨘,䨷,䱤,䲗,䵇,䶟,䶢|hong:仜,叿,吰,哄,嗊,嚝,垬,妅,娂,宏,宖,弘,彋,揈,撔,晎,汯,泓,洪,浤,渱,渹,潂,澋,澒,灴,烘,焢,玒,玜,硔,硡,竑,竤,篊,粠,紅,紘,紭,綋,红,纮,翃,翝,耾,苰,荭,葒,葓,蕻,薨,虹,訇,訌,讧,谹,谼,谾,軣,輷,轟,轰,鈜,鉷,銾,鋐,鍧,閎,閧,闀,闂,闳,霐,霟,鞃,鬨,魟,鴻,鸿,黉,黌,㖓,㢬,㬴,㶹,䀧,䂫,䃔,䆖,䉺,䍔,䜫,䞑,䡌,䡏,䧆,䨎,䩑,䪦,䫹,䫺,䲨|tong:仝,佟,僮,勭,同,哃,嗵,囲,峂,庝,彤,恸,慟,憅,捅,晍,曈,朣,桐,桶,樋,橦,氃,浵,潼,炵,烔,熥,犝,狪,獞,痌,痛,眮,瞳,砼,秱,穜,童,筒,筩,粡,絧,統,綂,统,膧,茼,蓪,蚒,衕,赨,通,酮,鉖,鉵,銅,铜,餇,鮦,鲖,㛚,㠉,㠽,㣚,㣠,㤏,㪌,㮔,㸗,㼧,㼿,䂈,䆚,䆹,䮵,䳋,䴀,䶱|dai:代,侢,傣,叇,呆,呔,垈,埭,岱,帒,带,帯,帶,廗,待,怠,懛,戴,曃,柋,歹,殆,汏,瀻,獃,玳,瑇,甙,簤,紿,緿,绐,艜,蚮,袋,襶,貸,贷,蹛,軑,軚,軩,轪,迨,逮,霴,靆,鮘,鴏,黛,黱,㐲,㞭,㫹,㯂,㶡,㻖,㿃,䈆,䒫,䚞,䚟|ling:令,伶,凌,刢,另,呤,囹,坽,夌,姈,婈,孁,岭,岺,崚,嶺,彾,掕,昤,朎,柃,棂,櫺,欞,泠,淩,澪,瀮,灵,炩,燯,爧,狑,玲,琌,瓴,皊,砱,祾,秢,竛,笭,紷,綾,绫,羚,翎,聆,舲,苓,菱,蓤,蔆,蕶,蘦,蛉,衑,袊,裬,詅,跉,軨,輘,酃,醽,鈴,錂,铃,閝,阾,陵,零,霊,霗,霛,霝,靈,領,领,駖,魿,鯪,鲮,鴒,鸰,鹷,麢,齡,齢,龄,龗,㖫,㡵,㥄,㦭,㪮,㬡,㯪,㱥,㲆,㸳,㻏,㾉,䄥,䈊,䉁,䉖,䉹,䌢,䍅,䔖,䕘,䖅,䙥,䚖,䠲,䡼,䡿,䧙,䨩,䯍,䰱,䴇,䴒,䴫|chao:仦,仯,吵,嘲,巐,巢,巣,弨,怊,抄,晁,朝,樔,欩,漅,潮,炒,焯,煼,牊,眧,窲,繛,罺,耖,觘,訬,謿,超,轈,鄛,鈔,钞,麨,鼂,鼌,㶤,㷅,䄻,䎐,䏚,䬤,䰫|chang:仧,伥,倀,倡,偿,僘,償,兏,厂,厰,唱,嘗,嚐,场,場,塲,娼,嫦,尝,常,廠,徜,怅,悵,惝,敞,昌,昶,晿,暢,椙,氅,淐,猖,玚,琩,瑒,瑺,瓺,甞,畅,畼,肠,腸,膓,苌,菖,萇,蟐,裮,誯,鋹,鋿,錩,鏛,锠,長,镸,长,閶,阊,韔,鬯,鯧,鱨,鲳,鲿,鼚,㙊,㦂,㫤,䕋,䗅,䠀,䠆,䩨,䯴|sa:仨,卅,摋,撒,栍,桬,櫒,洒,潵,灑,脎,萨,薩,訯,鈒,钑,隡,靸,颯,飒,馺,㒎,㪪,㳐,㽂,䊛,䘮,䙣,䬃|men:们,們,悶,懑,懣,扪,捫,暪,椚,焖,燜,玣,璊,穈,菛,虋,鍆,钔,門,閅,门,闷,㡈,㥃,㦖,㨺,㱪,㵍,䊟,䝧,䫒|fan:仮,凡,凢,凣,勫,匥,反,噃,墦,奿,嬎,嬏,嬔,帆,幡,忛,憣,払,旙,旛,杋,柉,梵,棥,樊,橎,氾,汎,泛,滼,瀪,瀿,烦,煩,燔,犯,犿,璠,畈,番,盕,矾,礬,笲,笵,範,籓,籵,緐,繁,繙,羳,翻,膰,舤,舧,范,蕃,薠,藩,蘩,蠜,襎,訉,販,贩,蹯,軓,軬,轓,辺,返,釩,鐇,钒,颿,飜,飯,飰,饭,鱕,鷭,㕨,㝃,㠶,㤆,㴀,㶗,㸋,㺕,㼝,㽹,䀀,䀟,䉊,䉒,䊩,䋣,䋦,䌓,䐪,䒠,䒦,䛀,䡊,䣲,䪛,䪤,䫶,䭵,䮳|yang:仰,佒,佯,傟,养,劷,卬,咉,坱,垟,央,奍,姎,岟,崵,崸,徉,怏,恙,慃,懩,扬,抰,揚,攁,敭,旸,昜,暘,杨,柍,样,楊,楧,様,樣,殃,氜,氧,氱,泱,洋,漾,瀁,炀,炴,烊,煬,珜,疡,痒,瘍,癢,眏,眻,礢,禓,秧,紻,羊,羏,羕,羪,胦,蛘,詇,諹,軮,輰,鉠,鍈,鍚,鐊,钖,阦,阳,陽,雵,霷,鞅,颺,飏,養,駚,鰑,鴦,鴹,鸉,鸯,㔦,㟅,㨾,㬕,㺊,㿮,䁑,䇦,䑆,䒋,䖹,䬗,䬬,䬺,䭐,䵮|wo:仴,倭,偓,卧,唩,喔,婐,婑,媉,幄,我,挝,捰,捾,握,撾,斡,楃,沃,涡,涹,渥,渦,濣,焥,猧,瓁,瞃,硪,窝,窩,肟,腛,臒,臥,莴,萵,蜗,蝸,踒,齷,龌,㠛,㦱,㧴,㱧,䁊,䠎,䰀|jian:件,侟,俭,俴,倹,健,僭,儉,兼,冿,减,剑,剣,剪,剱,劍,劎,劒,劔,囏,囝,坚,堅,墹,奸,姦,姧,寋,尖,帴,幵,建,弿,彅,徤,惤,戋,戔,戩,戬,拣,挸,捡,揀,揃,搛,撿,擶,旔,暕,枧,柬,栫,梘,检,検,椷,椾,楗,榗,槛,樫,橺,檢,檻,櫼,歼,殱,殲,毽,洊,涧,渐,減,湔,湕,溅,漸,澗,濺,瀐,瀳,瀸,瀽,煎,熞,熸,牋,牮,犍,猏,玪,珔,瑊,瑐,监,監,睑,睷,瞯,瞷,瞼,硷,碊,碱,磵,礀,礆,礛,笕,笺,筧,简,箋,箭,篯,簡,籛,糋,絸,緘,縑,繝,繭,缄,缣,翦,聻,肩,腱,臶,舰,艦,艰,艱,茧,荐,菅,菺,葌,葏,葥,蒹,蕑,蕳,薦,藆,虃,螹,蠒,袸,裥,襇,襉,襺,見,覵,覸,见,詃,諓,諫,謇,謭,譼,譾,谏,谫,豜,豣,賎,賤,贱,趝,趼,跈,践,踐,踺,蹇,轞,釼,鉴,鋻,鍳,鍵,鏩,鐗,鐧,鑑,鑒,鑬,鑯,鑳,锏,键,閒,間,间,靬,鞬,鞯,韀,韉,餞,餰,饯,馢,鬋,鰎,鰔,鰜,鰹,鲣,鳒,鳽,鵳,鶼,鹣,鹸,鹻,鹼,麉,㓺,㔋,㔓,㣤,㦗,㨴,㨵,㯺,㰄,㳨,㶕,㺝,䄯,䅐,䇟,䉍,䛳,䟅,䟰,䤔,䥜,䧖,䩆,䬻,䭈,䭕,䭠,䮿,䯛,䯡,䵖,䵛,䵡,䵤,䶠|jia:价,佳,假,傢,價,加,叚,唊,嗧,嘉,圿,埉,夹,夾,婽,嫁,宊,家,岬,幏,徦,恝,戛,戞,扴,抸,拁,斚,斝,架,枷,梜,椵,榎,榢,槚,檟,毠,泇,浃,浹,犌,猳,玾,珈,甲,痂,瘕,稼,笳,糘,耞,胛,脥,腵,荚,莢,葭,蛱,蛺,袈,袷,裌,豭,貑,賈,贾,跏,跲,迦,郏,郟,鉀,鉫,鋏,鎵,钾,铗,镓,頬,頰,颊,餄,駕,驾,鴶,鵊,麚,㕅,㪴,㮖,㼪,㿓,䀫,䁍,䑝,䕛,䛟,䩡|yao:仸,倄,偠,傜,吆,咬,喓,嗂,垚,堯,夭,妖,姚,婹,媱,宎,尧,尭,岆,峣,崾,嶢,嶤,幺,徭,徺,愮,抭,揺,搖,摇,摿,暚,曜,曣,杳,枖,柼,楆,榚,榣,殀,殽,溔,烑,熎,燿,爻,狕,猺,獟,珧,瑤,瑶,眑,矅,磘,祅,穾,窅,窈,窑,窔,窯,窰,筄,繇,纅,耀,肴,腰,舀,艞,苭,药,葯,葽,蓔,薬,藥,蘨,袎,要,覞,訞,詏,謠,謡,讑,谣,軺,轺,遙,遥,邀,銚,鎐,鑰,闄,靿,顤,颻,飖,餆,餚,騕,鰩,鳐,鴁,鴢,鷂,鷕,鹞,鼼,齩,㔽,㝔,㞁,㟱,㢓,㨱,㫏,㫐,㮁,㴭,㵸,㿑,㿢,䁏,䁘,䂚,䆙,䆞,䉰,䋂,䋤,䌊,䌛,䍃,䑬,䔄,䖴,䙅,䚺,䚻,䢣,䬙,䴠,䶧|fen:份,偾,僨,分,吩,坆,坋,坟,墳,奋,奮,妢,岎,帉,幩,弅,忿,愤,憤,昐,朆,枌,梤,棻,棼,橨,氛,汾,瀵,炃,焚,燌,燓,玢,瞓,秎,竕,粉,粪,糞,紛,纷,羒,羵,翂,肦,膹,芬,蒶,蕡,蚠,蚡,衯,訜,豮,豶,躮,轒,酚,鈖,鐼,隫,雰,餴,饙,馚,馩,魵,鱝,鲼,鳻,黂,黺,鼖,鼢,㖹,㥹,㮥,㷊,㸮,㿎,䩿,䯨,䴅|di:仾,低,俤,偙,僀,厎,呧,唙,啇,啲,嘀,嚁,地,坔,坻,埊,埞,堤,墑,墬,奃,娣,媂,嫡,嶳,帝,底,廸,弚,弟,弤,彽,怟,慸,抵,拞,掋,摕,敌,敵,旳,杕,枤,柢,梊,梑,棣,氐,涤,滌,滴,焍,牴,狄,玓,甋,眱,睇,砥,碲,磾,祶,禘,笛,第,篴,籴,糴,締,缔,羝,翟,聜,肑,腣,苐,苖,荻,菂,菧,蒂,蔋,蔐,蔕,藡,蝃,螮,袛,覿,觌,觝,詆,諦,诋,谛,豴,趆,踶,軧,迪,递,逓,遞,遰,邸,釱,鉪,鍉,鏑,镝,阺,隄,靮,鞮,頔,馰,骶,髢,魡,鯳,鸐,㡳,㢩,㣙,㦅,㪆,㭽,㰅,㹍,㼵,䀸,䀿,䂡,䊮,䍕,䏑,䑭,䑯,䞶,䟡,䢑,䣌,䧝,䨀,䨤,䩘,䩚,䮤,䯼,䱃,䱱,䴞,䵠,䶍|fang:仿,倣,匚,坊,埅,堏,妨,彷,房,放,方,旊,昉,昘,枋,淓,牥,瓬,眆,紡,纺,肪,舫,芳,蚄,訪,访,趽,邡,鈁,錺,钫,防,髣,魴,鲂,鴋,鶭,㑂,㕫,㤃,㧍,㯐,䢍,䦈,䲱|pei:伂,佩,俖,呸,培,姵,嶏,帔,怌,斾,旆,柸,毰,沛,浿,珮,笩,肧,胚,蓜,衃,裴,裵,賠,赔,轡,辔,配,醅,錇,锫,阫,陪,陫,霈,馷,㟝,㤄,㧩,㫲,㳈,䊃,䣙,䪹,䫠,䲹|diao:伄,凋,刁,刟,叼,吊,奝,屌,弔,弴,彫,扚,掉,殦,汈,琱,瘹,瞗,碉,窎,窵,竨,簓,蓧,藋,虭,蛁,訋,調,调,貂,釣,鈟,銱,鋽,鑃,钓,铞,雕,雿,鮉,鯛,鲷,鳭,鵰,鼦,㒛,㪕,㹿,䂪,䂽,䉆,䔙,䠼,䵲|dun:伅,吨,噸,囤,墩,墪,壿,庉,惇,憞,撉,撴,敦,橔,沌,潡,炖,燉,犜,獤,盹,盾,砘,碷,礅,腞,蜳,趸,踲,蹲,蹾,躉,逇,遁,遯,鈍,钝,頓,顿,驐,㬿,䤜|xin:伈,伩,信,俽,噷,噺,囟,妡,嬜,孞,廞,心,忄,忻,惞,新,昕,杺,枔,欣,歆,潃,炘,焮,盺,脪,舋,芯,莘,薪,衅,訢,訫,軐,辛,邤,釁,鈊,鋅,鐔,鑫,锌,阠,顖,馨,馫,馸,鬵,㐰,㚯,㛛,㭄,䒖,䚱,䛨,䜗,䜣,䰼|ai:伌,僾,凒,叆,哀,哎,唉,啀,嗌,嗳,嘊,噯,埃,塧,壒,娾,嫒,嬡,嵦,愛,懓,懝,挨,捱,敱,敳,昹,暧,曖,欸,毐,溰,溾,濭,爱,瑷,璦,癌,皑,皚,皧,瞹,矮,砹,硋,碍,礙,艾,蔼,薆,藹,譪,譺,賹,躷,鎄,鑀,锿,隘,霭,靄,靉,餲,馤,鱫,鴱,㑸,㕌,㗒,㗨,㘷,㝶,㢊,㤅,㱯,㿄,䀳,䅬,䑂,䔽,䝽,䠹,䨠,䬵,䶣|xiu:休,俢,修,咻,嗅,岫,庥,朽,樇,溴,滫,烋,烌,珛,琇,璓,秀,糔,綇,綉,繍,繡,绣,羞,脙,脩,臹,苬,螑,袖,裦,褎,褏,貅,銝,銹,鎀,鏅,鏥,鏽,锈,飍,饈,馐,髤,髹,鮴,鵂,鸺,齅,㗜,㱙,㾋|nu:伖,伮,傉,努,奴,孥,弩,怒,搙,砮,笯,胬,駑,驽,㚢,䢞|huo:伙,佸,俰,剨,劐,吙,咟,嗀,嚄,嚯,嚿,夥,夻,奯,惑,或,捇,掝,擭,攉,旤,曤,檴,沎,活,湱,漷,濩,瀖,火,獲,癨,眓,矆,矐,祸,禍,秮,秳,穫,耠,耯,臛,艧,获,蒦,藿,蠖,謋,豁,貨,货,邩,鈥,鍃,鑊,钬,锪,镬,閄,雘,霍,靃,騞,㗲,㘞,㦜,㦯,㨯,㯉,㸌,䁨,䂄,䄀,䄆,䄑,䉟,䋭,䣶,䦚,䯏,䰥|hui:会,佪,僡,儶,匯,卉,咴,哕,喙,嘒,噅,噕,噦,嚖,囘,回,囬,圚,婎,媈,孈,寭,屷,幑,廻,廽,彗,彙,彚,徻,徽,恚,恛,恢,恵,悔,惠,慧,憓,懳,拻,挥,揮,撝,晖,晦,暉,暳,會,桧,楎,槥,橞,檅,檓,檜,櫘,毀,毁,毇,汇,泋,洃,洄,浍,湏,滙,潓,澮,瀈,灰,灳,烠,烣,烩,烪,煇,燬,燴,獩,珲,琿,璤,璯,痐,瘣,睳,瞺,禈,秽,穢,篲,絵,繢,繪,绘,缋,翙,翚,翬,翽,芔,茴,荟,蔧,蕙,薈,薉,藱,虺,蚘,蛔,蛕,蜖,螝,蟪,袆,褘,詯,詼,誨,諱,譓,譭,譮,譿,讳,诙,诲,豗,賄,贿,輝,辉,迴,逥,鏸,鐬,闠,阓,隓,隳,靧,韢,頮,顪,餯,鮰,鰴,麾,㑰,㑹,㒑,㜇,㞧,㤬,㥣,㨤,㨹,㩓,㩨,㬩,㰥,㱱,㷄,㷐,㻅,䂕,䃣,䅏,䇻,䌇,䏨,䕇,䙌,䙡,䛛,䛼,䜋,䤧,䧥,䩈,䫭|che:伡,俥,偖,勶,唓,坼,奲,屮,彻,徹,扯,掣,撤,撦,澈,烢,烲,爡,瞮,砗,硨,硩,聅,莗,蛼,車,车,迠,頙,㔭,㥉,㨋,㬚,㯙,㱌,㵃,㵔,㾝,㿭,䁤,䋲,䑲,䒆,䚢,䛸,䜠,䞣,䧪,䨁,䰩|xun:伨,侚,偱,勋,勛,勲,勳,卂,噀,噚,嚑,坃,埙,塤,壎,壦,奞,寻,尋,峋,巡,巽,廵,徇,循,恂,愻,揗,攳,旬,曛,杊,栒,桪,樳,殉,殾,毥,汛,洵,浔,潯,灥,焄,熏,燂,燅,燖,燻,爋,狥,獯,珣,璕,矄,窨,紃,纁,臐,荀,蔒,蕈,薫,薰,蘍,蟳,襑,訊,訓,訙,詢,训,讯,询,賐,迅,迿,逊,遜,鄩,醺,鑂,顨,馴,駨,驯,鱏,鱘,鲟,㜄,㝁,㢲,㨚,㰊,㰬,㽦,䋸,䑕,䖲,䙉,䛜,䞊,䭀|gu:估,傦,僱,凅,古,咕,唂,唃,啒,嘏,固,堌,夃,姑,嫴,孤,尳,峠,崓,崮,怘,愲,扢,故,柧,梏,棝,榖,榾,橭,毂,汩,沽,泒,淈,濲,瀔,焸,牯,牿,痼,皷,盬,瞽,硲,祻,稒,穀,笟,箍,箛,篐,糓,縎,罛,罟,羖,股,脵,臌,菇,菰,蓇,薣,蛄,蛊,蛌,蠱,觚,詁,诂,谷,軱,軲,轂,轱,辜,逧,酤,鈲,鈷,錮,钴,锢,雇,頋,顧,顾,餶,馉,骨,鮕,鯝,鲴,鴣,鵠,鶻,鸪,鹄,鹘,鼓,鼔,㒴,㚉,㧽,㯏,㼋,㽽,㾶,䀇,䀜,䀦,䀰,䅽,䊺,䍍,䍛,䐨,䓢,䜼,䡩,䮩,䵻,䶜|ni:伱,伲,你,倪,儗,儞,匿,坭,埿,堄,妮,婗,嫟,嬺,孴,尼,屔,屰,怩,惄,愵,抳,拟,掜,擬,旎,昵,晲,暱,柅,棿,檷,氼,泥,淣,溺,狔,猊,痆,眤,睨,秜,籾,縌,胒,腻,膩,臡,苨,薿,蚭,蜺,觬,貎,跜,輗,迡,逆,郳,鈮,鉨,鑈,铌,隬,霓,馜,鯢,鲵,麑,齯,㞾,㠜,㣇,㥾,㦐,㪒,㲻,㵫,㹸,䁥,䕥,䘌,䘦,䘽,䛏,䝚,䦵,䧇,䭲,䰯,䵑,䵒|ban:伴,办,半,坂,姅,岅,怑,扮,扳,拌,搬,攽,斑,斒,昄,朌,板,湴,版,班,瓣,瓪,瘢,癍,秚,粄,絆,绊,舨,般,蝂,螁,螌,褩,辦,辬,鈑,鉡,钣,闆,阪,靽,頒,颁,魬,㚘,㩯,㪵,㸞,㺜,䉽,䕰,䬳|xu:伵,侐,俆,偦,冔,勖,勗,卹,叙,呴,喣,嘘,噓,垿,墟,壻,姁,婿,媭,嬃,幁,序,徐,恤,慉,戌,揟,敍,敘,旭,旴,昫,暊,朂,栩,楈,槒,欨,欰,欻,歔,歘,殈,汿,沀,洫,湑,溆,漵,潊,烅,烼,煦,獝,珝,珬,畜,疞,盢,盨,盱,瞁,瞲,砉,稰,稸,窢,糈,絮,続,緒,緖,縃,續,绪,续,聟,胥,蒣,蓄,蓿,蕦,藇,藚,虗,虚,虛,蝑,訏,許,訹,詡,諝,譃,许,诩,谞,賉,鄦,酗,醑,銊,鑐,需,須,頊,须,顼,驉,鬚,魆,魖,鱮,㐨,㑔,㑯,㕛,㖅,㗵,㘧,㚜,㜅,㜿,㞊,㞰,㤢,㥠,㦽,㰲,㵰,㷦,㺷,㾥,䂆,䅡,䋶,䍱,䔓,䘏,䙒,䛙,䜡,䢕,䣱,䣴,䦗,䦽,䬔,䱛,䳳|zhou:伷,侜,僽,冑,周,呪,咒,咮,喌,噣,嚋,妯,婤,宙,州,帚,徟,昼,晝,晭,洀,洲,淍,炿,烐,珘,甃,疛,皱,皺,盩,睭,矪,碡,箒,籀,籒,籕,粙,粥,紂,縐,纣,绉,肘,胄,舟,荮,菷,葤,詋,謅,譸,诌,诪,賙,赒,軸,輈,輖,轴,辀,週,郮,酎,銂,霌,駎,駲,騆,驟,骤,鯞,鵃,鸼,㑇,㑳,㔌,㛩,㥮,㼙,㾭,䇠,䈙,䋓,䎻,䏲,䐍,䖞,䛆,䩜,䶇|shen:伸,侁,侺,兟,呻,哂,堔,妽,姺,娠,婶,嬸,审,宷,審,屾,峷,弞,愼,慎,扟,抌,昚,曋,柛,椮,椹,榊,氠,沈,涁,深,渖,渗,滲,瀋,燊,珅,甚,甡,甧,申,瘆,瘮,眒,眘,瞫,矤,矧,砷,神,祳,穼,籶,籸,紳,绅,罙,罧,肾,胂,脤,腎,葠,蓡,蔘,薓,蜃,裑,覾,訠,訷,詵,諗,讅,诜,谂,谉,身,邥,鉮,鋠,頣,駪,魫,鯓,鯵,鰰,鰺,鲹,鵢,㔤,㜤,㥲,㰂,㰮,㵊,㵕,㾕,䆦,䰠|qu:伹,佉,佢,刞,劬,匤,匷,区,區,厺,去,取,呿,坥,娶,屈,岖,岨,岴,嶇,忂,憈,戵,抾,敺,斪,曲,朐,朑,欋,氍,浀,淭,渠,灈,璖,璩,癯,磲,祛,竘,竬,筁,籧,粬,紶,絇,翑,翵,耝,胊,胠,臞,菃,葋,蕖,蘧,蛆,蛐,蝺,螶,蟝,蠷,蠼,衐,衢,袪,覰,覷,覻,觑,詓,詘,誳,诎,趋,趣,趨,躣,躯,軀,軥,迲,郥,鑺,閴,闃,阒,阹,駆,駈,驅,驱,髷,魼,鰸,鱋,鴝,鸜,鸲,麮,麯,麴,麹,黢,鼁,鼩,齲,龋,㖆,㜹,㠊,㣄,㧁,㫢,㯫,㰦,㲘,䀠,䁦,䂂,䋧,䒧,䝣,䞤,䟊,䠐,䵶,䶚|beng:伻,嘣,埄,埲,塴,奟,崩,嵭,泵,琣,琫,甏,甭,痭,祊,絣,綳,繃,绷,菶,跰,蹦,迸,逬,鏰,镚,閍,鞛,㑟,㱶,㷯,䋽,䙀,䨻,䩬,䭰,䳞|ga:伽,嘎,嘠,噶,尕,尜,尬,旮,玍,釓,錷,钆,魀|dian:佃,傎,典,厧,唸,坫,垫,墊,壂,奌,奠,婝,婰,嵮,巅,巓,巔,店,惦,扂,掂,攧,敁,敟,椣,槙,橂,殿,淀,滇,澱,点,玷,琔,电,甸,瘨,癜,癫,癲,碘,磹,簟,蒧,蕇,蜔,踮,蹎,鈿,钿,阽,電,靛,顚,顛,颠,驔,點,齻,㓠,㚲,㝪,㞟,㥆,㵤,㶘,㸃,㼭,䍄,䓦,䟍,䧃|han:佄,傼,兯,函,凾,厈,含,咁,哻,唅,喊,圅,垾,娢,嫨,寒,屽,崡,嵅,悍,憨,憾,扞,捍,撖,撼,旱,晗,晘,晥,暵,梒,汉,汗,浛,浫,涆,涵,淊,漢,澏,瀚,焊,焓,熯,爳,猂,琀,甝,皔,睅,筨,罕,翰,肣,莟,菡,蔊,蘫,虷,蚶,蛿,蜬,蜭,螒,譀,谽,豃,邗,邯,酣,釬,銲,鋎,鋡,閈,闬,雗,韓,韩,頇,頷,顄,顸,颔,馠,馯,駻,鬫,魽,鶾,鼾,㑵,㒈,㖤,㘎,㘕,㘚,㙈,㙔,㙳,㜦,㟏,㟔,㢨,㨔,㪋,㮀,㲦,㵄,㵎,㶰,㸁,㺖,㼨,㽉,㽳,䁔,䈄,䌍,䍐,䍑,䎯,䏷,䐄,䓍,䓿,䕿,䖔,䗙,䘶,䛞,䤴,䥁,䧲,䨡,䫲,䮧,䶃|bi:佊,佖,俾,偪,匂,匕,吡,哔,啚,嗶,坒,堛,壁,夶,奰,妣,妼,婢,嬖,嬶,屄,币,幣,幤,庇,庳,廦,弊,弻,弼,彃,彼,必,怭,愊,愎,敝,斃,朼,枈,柀,柲,梐,楅,比,毕,毖,毙,毴,沘,湢,滗,滭,潷,濞,煏,熚,狴,獘,獙,珌,璧,畀,畁,畢,疕,疪,痹,痺,皀,皕,碧,禆,秕,稫,笔,筆,筚,箅,箆,篦,篳,粃,粊,綼,縪,繴,罼,聛,胇,腷,臂,舭,苾,荜,荸,萆,萞,蓖,蓽,蔽,薜,蜌,螕,袐,裨,襅,襞,襣,觱,詖,诐,豍,貏,貱,贔,赑,跸,蹕,躃,躄,辟,逼,避,邲,鄙,鄨,鄪,鉍,鎞,鏎,鐴,铋,閇,閉,閟,闭,陛,鞞,鞸,韠,飶,饆,馝,駜,驆,髀,髲,魓,鮅,鰏,鲾,鵖,鷝,鷩,鼊,鼻,㓖,㗉,㘠,㘩,㙄,㚰,㠲,㡀,㡙,㢰,㢶,㢸,㧙,㪏,㪤,㮰,㮿,㯇,㱸,㳼,㵥,㵨,㹃,㻫,㻶,㿫,䀣,䁹,䃾,䄶,䇷,䊧,䋔,䌟,䎵,䏢,䏶,䕗,䖩,䘡,䟆,䟤,䠋,䣥,䦘,䧗,䨆,䩛,䪐,䫁,䫾,䭮,䮡,䯗,䵄|zhao:佋,兆,召,啁,垗,妱,巶,找,招,旐,昭,曌,枛,棹,櫂,沼,炤,照,燳,爫,狣,瑵,盄,瞾,窼,笊,箌,罀,罩,羄,肁,肇,肈,詔,诏,赵,趙,釗,鉊,鍣,钊,駋,鮡,㕚,㡽,㨄,㷖,㺐,䃍,䈃,䈇,䍜,䍮,䝖,䮓|ci:佌,佽,偨,刺,刾,呲,嗭,垐,堲,嬨,庛,慈,朿,柌,栨,次,此,泚,濨,玼,珁,瓷,甆,疵,皉,磁,礠,祠,糍,絘,縒,茈,茦,茨,莿,薋,蛓,螆,蠀,詞,词,賜,赐,趀,跐,辝,辞,辤,辭,鈶,雌,飺,餈,骴,鴜,鶿,鷀,鹚,㓨,㘂,㘹,㞖,㠿,㡹,㢀,㤵,㩞,㹂,䂣,䆅,䈘,䓧,䖪,䗹,䛐,䦻,䧳,䨏,䭣,䯸,䰍,䲿,䳄,䳐|zuo:佐,作,侳,做,咗,唑,坐,岝,岞,左,座,怍,捽,昨,柞,椊,祚,秨,稓,筰,糳,繓,胙,莋,葃,葄,蓙,袏,鈼,阼,飵,㑅,㘀,㘴,㛗,㝾,㭮,㸲,䋏,䎰,䔘,䝫,䞰|ti:体,倜,偍,剃,剔,厗,啼,嗁,嚏,嚔,媞,屉,屜,崹,徲,悌,悐,惕,惖,惿,戻,挮,掦,提,揥,替,梯,楴,歒,殢,洟,涕,渧,漽,珶,瑅,瓋,碮,稊,籊,綈,緹,绨,缇,罤,蕛,薙,蝭,裼,褅,謕,趧,趯,踢,蹄,蹏,躰,軆,逖,逷,遆,醍,銻,鍗,鐟,锑,題,题,騠,骵,體,髰,鬀,鬄,鮷,鯷,鳀,鴺,鵜,鶗,鶙,鷈,鷉,鹈,㖒,㗣,㡗,㣢,㬱,㯩,䅠,䌡,䎮,䔶,䙗,䚣,䛱,䝰,䣡,䣽,䧅,䨑,䪆,䬾,䯜,䴘,䶏,䶑|zhan:佔,偡,占,噡,嫸,展,崭,嶃,嶄,嶘,嶦,惉,战,戦,戰,拃,搌,斩,斬,旃,旜,栈,栴,桟,棧,榐,橏,毡,氈,氊,沾,湛,澶,琖,皽,盏,盞,瞻,站,粘,綻,绽,菚,薝,蘸,虥,虦,蛅,覱,詀,詹,譫,讝,谵,趈,蹍,輚,輾,轏,辗,邅,醆,閚,霑,颭,飐,飦,饘,驏,驙,骣,魙,鱣,鳣,鸇,鹯,黵,㞡,㟞,㠭,㣶,㺘,㻵,䁴,䋎,䎒,䗃,䘺,䟋,䡀,䩅,䪌,䱠,䱼|he:何,佫,劾,合,呵,咊,和,哬,啝,喝,嗃,嗬,垎,壑,姀,寉,峆,惒,抲,敆,曷,柇,核,楁,欱,毼,河,涸,渮,湼,澕,焃,煂,熆,熇,燺,爀,狢,癋,皬,盇,盉,盍,盒,碋,礉,禾,秴,篕,籺,粭,翮,翯,荷,菏,萂,蚵,螛,蠚,袔,褐,覈,訶,訸,詥,诃,貈,貉,賀,贺,赫,郃,鉌,鑉,閡,闔,阂,阖,隺,靍,靎,靏,鞨,頜,颌,饸,魺,鲄,鶡,鶴,鸖,鹖,鹤,麧,齃,齕,龁,龢,㓭,㔠,㕡,㕰,㥺,㦦,㪉,㬞,㭘,㭱,㮝,㮫,㵑,㷎,㷤,㹇,㿣,䃒,䅂,䎋,䒩,䓼,䕣,䚂,䞦,䢗,䪚,䫘,䳚,䳽,䴳,䵱,䶅|she:佘,厍,厙,奢,射,弽,慑,慴,懾,捨,摂,摄,摵,攝,檨,欇,涉,涻,渉,滠,灄,猞,畲,社,舌,舍,舎,蔎,虵,蛇,蛥,蠂,設,设,賒,賖,赊,赦,輋,韘,騇,麝,㒤,㢵,㭙,㰒,㴇,䀅,䁋,䁯,䂠,䄕,䌰,䞌,䠶,䤮,䬷,䵥|gou:佝,冓,勾,坸,垢,够,夠,姤,媾,岣,彀,搆,撀,构,枸,構,沟,溝,煹,狗,玽,笱,篝,簼,緱,缑,耇,耈,耉,苟,茩,蚼,袧,褠,覯,觏,訽,詬,诟,豿,購,购,遘,鈎,鉤,钩,雊,鞲,韝,㗕,㜌,㝅,㝤,㨌,㳶,㺃,䃓,䝭,䞀|ning:佞,侫,儜,凝,咛,嚀,嬣,宁,寍,寕,寗,寜,寧,拧,擰,柠,橣,檸,泞,澝,濘,狞,獰,甯,矃,聍,聹,薴,鑏,鬡,鸋,㝕,㣷,㲰,㿦,䔭,䗿,䭢|yong:佣,俑,傛,傭,勇,勈,咏,喁,嗈,噰,埇,塎,墉,壅,嫞,嵱,庸,廱,彮,怺,恿,悀,惥,愑,愹,慂,慵,拥,擁,柡,栐,槦,永,泳,涌,湧,滽,澭,灉,牅,用,甬,痈,癕,癰,砽,硧,禜,臃,苚,蛹,詠,踊,踴,邕,郺,鄘,醟,銿,鏞,镛,雍,雝,顒,颙,饔,鯒,鰫,鱅,鲬,鳙,鷛,㐯,㙲,㝘,㞲,㦷,㶲,㷏,㽫,䗤,䞻|wa:佤,劸,咓,哇,啘,嗗,嗢,娃,娲,媧,屲,徍,挖,搲,攨,洼,溛,漥,瓦,瓲,畖,砙,窊,窪,聉,腽,膃,蛙,袜,襪,邷,韈,韤,鼃,㧚,㰪,㼘,䎳,䚴,䠚|ka:佧,卡,咔,咖,咯,喀,垰,胩,裃,鉲|bao:佨,保,儤,剝,剥,勹,勽,包,堡,堢,報,媬,嫑,孢,宝,寚,寳,寶,忁,怉,报,抱,暴,曓,煲,爆,珤,窇,笣,緥,胞,苞,菢,萡,葆,蕔,薄,藵,虣,袌,褒,褓,襃,豹,賲,趵,鉋,鑤,铇,闁,雹,靌,靤,飹,飽,饱,駂,骲,髱,鮑,鲍,鳵,鴇,鸨,齙,龅,㙅,㙸,㫧,㲏,㲒,㵡,㻄,㿺,䈏,䎂,䤖,䥤,䨌,䨔,䪨,䭋,䳈,䳰,䴐|lao:佬,僗,劳,労,勞,咾,哰,唠,嗠,嘮,姥,嫪,崂,嶗,恅,憥,憦,捞,撈,朥,栳,橑,橯,浶,涝,澇,烙,牢,狫,珯,痨,癆,硓,磱,窂,簩,粩,老,耂,耢,耮,荖,蛯,蟧,軂,轑,酪,醪,銠,鐒,铑,铹,顟,髝,鮱,㗦,㞠,㟉,㟙,㟹,㧯,㨓,䃕,䇭,䕩,䜎,䝁,䝤,䲏,䳓,䵏|bai:佰,兡,呗,唄,庍,拜,拝,挀,捭,掰,摆,擺,敗,柏,栢,猈,瓸,白,百,稗,竡,粨,粺,絔,薭,襬,贁,败,鞁,韛,㗑,㗗,㠔,㼟,㼣,㿟,䒔,䙓,䢙,䳆,䴽|ming:佲,冥,凕,名,命,姳,嫇,慏,掵,明,暝,朙,榠,洺,溟,猽,眀,眳,瞑,茗,蓂,螟,覭,詺,鄍,酩,銘,铭,鳴,鸣,㝠,㟰,㫥,䄙,䆨,䆩,䊅,䒌,䫤|hen:佷,很,恨,拫,狠,痕,詪,鞎,㯊,䓳|quan:佺,全,券,劝,勧,勸,啳,圈,圏,埢,姾,婘,孉,峑,巏,巻,恮,悛,惓,拳,搼,权,棬,椦,楾,権,權,汱,泉,洤,湶,烇,牶,牷,犈,犬,犭,瑔,甽,畎,痊,硂,筌,絟,綣,縓,绻,腃,荃,葲,虇,蜷,蠸,觠,詮,诠,跧,踡,輇,辁,醛,銓,鐉,铨,闎,韏,顴,颧,駩,騡,鬈,鰁,鳈,齤,㒰,㟨,㟫,䀬,䄐,䊎,䑏,䟒,䠰|tiao:佻,嬥,宨,岧,岹,庣,恌,挑,旫,晀,朓,条,條,樤,眺,祒,祧,窕,窱,笤,粜,糶,絩,聎,脁,芀,蓚,蓨,蜩,螩,覜,誂,趒,跳,迢,鋚,鎥,铫,鞗,頫,髫,鯈,鰷,鲦,齠,龆,㑿,㟘,㸠,䎄,䒒,䖺,䟭,䠷,䩦,䯾,䱔,䳂|xing:侀,倖,兴,刑,哘,型,垶,塂,姓,娙,婞,嬹,幸,形,性,悻,惺,擤,星,曐,杏,洐,涬,煋,狌,猩,瑆,皨,睲,硎,箵,篂,緈,腥,臖,興,荇,莕,蛵,行,裄,觪,觲,謃,邢,郉,醒,鈃,鉶,銒,鋞,钘,铏,陉,陘,騂,骍,鮏,鯹,㐩,㓑,㓝,㝭,㣜,㨘,㮐,㼛,㼬,䁄,䂔,䓷,䛭,䣆,䤯,䰢,䳙|kan:侃,偘,冚,刊,勘,坎,埳,堪,堿,塪,墈,崁,嵁,惂,戡,栞,欿,歁,看,瞰,矙,砍,磡,竷,莰,衎,輡,轁,轗,闞,阚,顑,龕,龛,㸝,䀍,䘓,䶫|lai:來,俫,倈,唻,婡,崃,崍,庲,徕,徠,来,梾,棶,涞,淶,濑,瀨,瀬,猍,琜,癞,癩,睐,睞,筙,箂,籁,籟,莱,萊,藾,襰,賚,賴,赉,赖,逨,郲,錸,铼,頼,顂,騋,鯠,鵣,鶆,麳,㚓,㠣,㥎,㾢,䂾,䄤,䅘,䋱,䓶,䚅,䠭,䧒,䲚|chi:侈,侙,俿,傺,勅,匙,卶,叱,叺,吃,呎,哧,啻,喫,嗤,噄,坘,垑,墀,妛,媸,尺,岻,弛,彨,彲,彳,恜,恥,慗,憏,懘,抶,拸,持,摛,攡,敕,斥,杘,欼,歭,歯,池,泜,淔,湁,漦,灻,炽,烾,熾,瓻,痓,痴,痸,瘛,癡,眵,瞝,竾,笞,筂,篪,粚,糦,絺,翄,翅,翤,翨,耛,耻,肔,胣,胵,腟,茌,荎,蚇,蚩,蚳,螭,袲,袳,裭,褫,訵,誺,謘,豉,貾,赤,赿,趍,趩,跮,踟,迟,迣,遅,遟,遫,遲,鉓,鉹,銐,雴,飭,饎,饬,馳,驰,魑,鴟,鵄,鶒,鷘,鸱,麶,黐,齒,齝,齿,㒆,㓼,㓾,㔑,㘜,㙜,㞴,㞿,㟂,㡿,㢁,㢋,㢮,㮛,㱀,㳏,㶴,㽚,䆍,䇼,䈕,䊼,䐤,䑛,䔟,䗖,䙙,䛂,䜄,䜵,䜻,䞾,䟷,䠠,䤲,䪧,䮈,䮻,䰡,䳵,䶔,䶵|kua:侉,咵,垮,夸,姱,挎,晇,胯,舿,誇,跨,銙,骻,㐄,䋀|guang:侊,俇,僙,光,咣,垙,姯,广,広,廣,撗,桄,欟,洸,灮,炗,炚,炛,烡,犷,獷,珖,硄,胱,臦,臩,茪,輄,逛,銧,黆,㫛|mi:侎,冖,冞,冪,咪,嘧,塓,孊,宓,宻,密,峚,幂,幎,幦,弥,弭,彌,戂,擟,攠,敉,榓,樒,櫁,汨,沕,沵,泌,洣,淧,渳,滵,漞,濔,濗,瀰,灖,熐,爢,猕,獼,瓕,眫,眯,瞇,祕,祢,禰,秘,簚,米,粎,糜,糸,縻,羃,羋,脒,芈,葞,蒾,蔝,蔤,藌,蘼,蜜,蝆,袮,覓,覔,覛,觅,詸,謎,謐,谜,谧,踎,迷,醚,醾,醿,釄,銤,镾,靡,鸍,麊,麋,麛,鼏,㜆,㜷,㝥,㟜,㠧,㣆,㥝,㨠,㩢,㫘,㰽,㳴,㳽,㴵,㵋,㸏,㸓,䁇,䉾,䊳,䋛,䌏,䌐,䌕,䌘,䌩,䍘,䕳,䕷,䖑,䛉,䛑,䛧,䣾,䤉,䤍,䥸,䪾,䭧,䭩,䱊,䴢|an:侒,俺,儑,唵,啽,垵,埯,堓,婩,媕,安,岸,峖,庵,按,揞,晻,暗,案,桉,氨,洝,犴,玵,痷,盦,盫,罯,胺,腤,荌,菴,萻,葊,蓭,誝,諳,谙,豻,貋,銨,錌,铵,闇,隌,雸,鞌,鞍,韽,馣,鮟,鵪,鶕,鹌,黯,㜝,㟁,㱘,㸩,㽢,䁆,䅁,䅖,䎏,䎨,䜙,䬓,䮗,䯥|lu:侓,僇,剹,勎,勠,卢,卤,噜,嚕,嚧,圥,坴,垆,塶,塷,壚,娽,峍,庐,廘,廬,彔,录,戮,挔,捛,掳,摝,撸,擄,擼,攎,枦,栌,椂,樐,樚,橹,櫓,櫨,氇,氌,泸,淕,淥,渌,滷,漉,潞,澛,濾,瀂,瀘,炉,熝,爐,獹,玈,琭,璐,璷,瓐,甪,盝,盧,睩,矑,硉,硵,碌,磠,祿,禄,稑,穋,箓,簏,簬,簵,簶,籙,籚,粶,纑,罏,胪,膔,膟,臚,舮,舻,艣,艪,艫,芦,菉,蓾,蔍,蕗,蘆,虂,虏,虜,螰,蠦,觮,觻,賂,赂,趢,路,踛,蹗,輅,轆,轤,轳,辂,辘,逯,醁,鈩,錄,録,錴,鏀,鏕,鏴,鐪,鑥,鑪,镥,陆,陸,露,顱,颅,騄,騼,髗,魯,魲,鯥,鱸,鲁,鲈,鴼,鵦,鵱,鷺,鸕,鸬,鹭,鹵,鹿,麓,黸,㓐,㔪,㖨,㛬,㜙,㟤,㠠,㢚,㢳,㦇,㪐,㪖,㪭,㫽,㭔,㯝,㯟,㯭,㱺,㼾,㿖,䃙,䌒,䎑,䎼,䐂,䕡,䘵,䚄,䟿,䡎,䡜,䩮,䬛,䮉,䰕,䱚,䲐,䴪|mou:侔,劺,哞,恈,某,桙,洠,牟,眸,瞴,蟱,謀,谋,鉾,鍪,鴾,麰,㭌,䍒,䏬,䗋,䥐,䱕|cha:侘,偛,剎,叉,嗏,垞,奼,姹,察,岔,嵖,差,扠,扱,挿,插,揷,搽,杈,查,査,槎,檫,汊,猹,疀,碴,秅,紁,肞,臿,艖,芆,茬,茶,衩,褨,訍,詧,詫,诧,蹅,釵,銟,鍤,鎈,鑔,钗,锸,镲,靫,餷,馇,㛳,㢉,㢎,㢒,㣾,㤞,㪯,㫅,䁟,䆛,䊬,䑘,䒲,䓭,䕓,䟕,䡨,䤩,䰈,䲦,䶪|gong:供,兝,兣,公,共,功,匑,匔,厷,唝,塨,宫,宮,工,巩,幊,廾,弓,恭,愩,慐,拱,拲,攻,杛,栱,汞,熕,珙,碽,篢,糼,羾,肱,蚣,觥,觵,貢,贑,贡,躬,躳,輁,鞏,髸,龏,龔,龚,㓋,㔶,㤨,㧬,㫒,㭟,㯯,㺬,㼦,䂬,䇨,䡗,䢚|lv:侣,侶,儢,勴,吕,呂,哷,垏,寽,屡,屢,履,嵂,律,慮,旅,曥,梠,榈,櫖,櫚,氀,氯,滤,焒,爈,率,祣,稆,穞,穭,箻,絽,綠,緑,縷,繂,绿,缕,膂,膐,膢,葎,藘,虑,褛,褸,郘,鋁,鑢,铝,閭,闾,馿,驢,驴,鷜,㔧,㠥,㭚,㲶,㻲,㾔,䔞,䢖,䥨|zhen:侦,侲,偵,圳,塦,姫,嫃,寊,屒,帪,弫,抮,挋,振,揕,搸,敒,敶,斟,昣,朕,枕,栕,栚,桢,桭,楨,榛,槇,樼,殝,浈,湞,潧,澵,獉,珍,珎,瑧,甄,畛,疹,眕,眞,真,眹,砧,碪,祯,禎,禛,稹,箴,籈,紖,紾,絼,縝,縥,纼,缜,聄,胗,臻,萙,葴,蒖,蓁,薽,蜄,袗,裖,覙,診,誫,诊,貞,賑,贞,赈,軫,轃,轸,辴,遉,酙,針,鉁,鋴,錱,鍖,鍼,鎭,鎮,针,镇,阵,陣,震,靕,駗,鬒,鱵,鴆,鸩,黮,黰,㐱,㓄,㣀,㪛,㮳,㯢,㴨,䂦,䂧,䊶,䏖,䑐,䝩,䟴,䨯,䪴,䫬,䲴,䳲|ce:侧,側,冊,册,厕,厠,墄,廁,恻,惻,憡,拺,敇,测,測,畟,笧,策,筞,筴,箣,簎,粣,荝,萗,萴,蓛,㥽,㨲,㩍,䇲,䈟,䊂,䔴,䜺|kuai:侩,儈,凷,哙,噲,圦,块,塊,墤,巜,廥,快,擓,旝,狯,獪,筷,糩,脍,膾,蒯,郐,鄶,鱠,鲙,㔞,㙕,㙗,㟴,㧟,㬮,㱮,䈛,䓒,䭝,䯤,䶐|chai:侪,儕,勑,喍,囆,拆,柴,犲,瘥,祡,茝,虿,蠆,袃,豺,㑪,㳗,㾹,䓱,䘍|nong:侬,儂,农,哝,噥,弄,憹,挊,挵,欁,浓,濃,癑,禯,秾,穠,繷,脓,膿,蕽,襛,農,辳,醲,齈,㶶,䁸,䢉,䵜|hou:侯,候,厚,后,吼,吽,喉,垕,堠,帿,後,洉,犼,猴,瘊,睺,矦,篌,糇,翭,葔,豞,逅,郈,鄇,銗,鍭,餱,骺,鮜,鯸,鱟,鲎,鲘,齁,㕈,㖃,㗋,㤧,㫗,㬋,㮢,㸸,㺅,䂉,䗔,䙈,䞧,䪷,䫛,䳧|jiong:侰,僒,冂,冋,冏,囧,坰,埛,扃,泂,浻,澃,炯,烱,煚,煛,熲,燑,燛,窘,絅,綗,蘏,蘔,褧,迥,逈,顈,颎,駉,駫,㑋,㓏,㖥,㢠,㤯,㷗,㷡,䌹,䐃,䢛|nan:侽,南,喃,囡,娚,婻,戁,抩,揇,暔,枏,枬,柟,楠,湳,煵,男,畘,腩,莮,萳,蝻,諵,赧,遖,难,難,㓓,㫱,㽖,䁪,䈒,䔜,䔳,䕼,䛁,䶲|xiao:侾,俲,傚,削,効,呺,咲,哓,哮,啋,啸,嘋,嘐,嘨,嘯,嘵,嚣,嚻,囂,婋,孝,宯,宵,小,崤,庨,彇,恔,恷,憢,揱,撨,效,敩,斅,斆,晓,暁,曉,枭,枵,校,梟,櫹,歊,歗,毊,洨,消,涍,淆,滧,潇,瀟,灱,灲,焇,熽,猇,獢,痚,痟,皛,皢,硝,硣,穘,窙,笑,筱,筿,箫,篠,簘,簫,綃,绡,翛,肖,膮,萧,萷,蕭,藃,虈,虓,蟂,蟏,蟰,蠨,訤,詨,誟,誵,謏,謞,踃,逍,郩,銷,销,霄,驍,骁,髇,髐,魈,鴞,鴵,鷍,鸮,㑾,㔅,㗛,㚣,㤊,㬵,㹲,䊥,䒕,䒝,䕧,䥵|bian:便,匾,卞,变,変,峅,弁,徧,忭,惼,扁,抃,拚,揙,昪,汳,汴,炞,煸,牑,猵,獱,甂,砭,碥,稨,窆,笾,箯,籩,糄,編,緶,缏,编,艑,苄,萹,藊,蝙,褊,覍,變,貶,贬,辡,辧,辨,辩,辪,辫,辮,辯,边,遍,邉,邊,釆,鍽,閞,鞭,頨,鯾,鯿,鳊,鴘,㝸,㣐,㦚,㭓,㲢,㳎,㳒,㴜,㵷,㺹,㻞,䁵,䉸,䒪,䛒,䡢,䪻|tui:俀,僓,娧,尵,推,煺,穨,脮,腿,蓷,藬,蘈,蛻,蜕,褪,蹆,蹪,退,隤,頹,頺,頽,颓,駾,骽,魋,㞂,㢈,㢑,㦌,㱣,㷟,㾯,㾼,㾽,㿉,㿗,䀃,䅪,䍾,䫋|cu:促,噈,媨,徂,憱,殂,猝,瘄,瘯,簇,粗,縬,蔟,觕,誎,趗,踧,蹙,蹴,蹵,酢,醋,顣,麁,麄,麤,鼀,㗤,㰗,䃚,䎌,䓚,䙯,䛤,䟟,䠓,䠞,䢐,䥄,䥘,䬨|e:俄,偔,僫,匎,卾,厄,吪,呃,呝,咢,咹,噁,噩,囮,垩,堊,堮,妸,妿,姶,娥,娿,婀,屙,屵,岋,峉,峨,峩,崿,廅,恶,悪,惡,愕,戹,扼,搤,搹,擜,枙,櫮,歞,歺,涐,湂,珴,琧,皒,睋,砈,砐,砨,硆,磀,腭,苊,莪,萼,蕚,蚅,蛾,蝁,覨,訛,詻,誐,諤,譌,讍,讹,谔,豟,軛,軶,轭,迗,遌,遏,遻,鄂,鈋,鋨,鍔,鑩,锇,锷,閼,阏,阨,阸,頞,頟,額,顎,颚,额,餓,餩,饿,騀,魤,鰐,鱷,鳄,鵈,鵝,鵞,鶚,鹅,鹗,齶,㓵,㔩,㕎,㖾,㗁,㟧,㠋,㡋,㦍,㧖,㩵,㮙,㱦,㷈,㼂,㼢,㼰,䄉,䆓,䑥,䑪,䓊,䔾,䕏,䖸,䙳,䛖,䝈,䞩,䣞,䩹,䫷,䱮,䳗,䳘,䳬|ku:俈,刳,哭,喾,嚳,圐,堀,崫,库,庫,扝,枯,桍,楛,焅,狜,瘔,矻,秙,窟,絝,绔,苦,袴,裤,褲,跍,郀,酷,骷,鮬,㒂,㠸,䇢|jun:俊,儁,军,君,呁,均,埈,姰,寯,峻,懏,捃,攈,晙,桾,汮,浚,濬,焌,燇,珺,畯,皲,皸,皹,碅,竣,筠,箘,箟,莙,菌,蚐,蜠,袀,覠,軍,郡,鈞,銁,銞,鍕,钧,陖,餕,馂,駿,骏,鮶,鲪,鵔,鵕,鵘,麇,麏,麕,㑺,㒞,㓴,㕙,㝦,㴫,㻒,㽙,䇹,䕑,䜭,䝍|zu:俎,傶,卆,卒,哫,崒,崪,族,爼,珇,祖,租,稡,箤,組,组,菹,葅,蒩,詛,謯,诅,足,踤,踿,鎺,鏃,镞,阻,靻,㞺,㰵,㲞,䅸,䔃,䖕,䚝,䯿,䱣|hun:俒,倱,圂,婚,忶,惛,惽,慁,掍,昏,昬,棔,殙,浑,涽,混,渾,溷,焝,睧,睯,繉,荤,葷,觨,諢,诨,轋,閽,阍,餛,馄,魂,鼲,㑮,㥵,㨡,䅙,䅱,䚠,䛰,䧰,䫟,䰟,䴷|su:俗,傃,僳,嗉,嗽,囌,塐,塑,夙,嫊,宿,愫,愬,憟,梀,榡,樎,樕,橚,櫯,殐,泝,洬,涑,溯,溸,潚,潥,玊,珟,璛,甦,碿,稣,穌,窣,簌,粛,粟,素,縤,肃,肅,膆,苏,蔌,藗,蘇,蘓,觫,訴,謖,诉,谡,趚,蹜,速,遡,遬,酥,鋉,餗,驌,骕,鯂,鱐,鷫,鹔,㑉,㑛,㓘,㔄,㕖,㜚,㝛,㨞,㩋,㪩,㬘,㯈,㴋,㴑,㴼,䃤,䅇,䌚,䎘,䏋,䑿,䔎,䘻,䛾,䥔|lia:俩,倆|pai:俳,哌,徘,拍,排,棑,派,湃,牌,犤,猅,磗,箄,簰,蒎,輫,鎃,㭛,㵺,䖰|biao:俵,儦,墂,婊,幖,彪,摽,杓,标,標,檦,淲,滮,瀌,灬,熛,爂,猋,瘭,穮,脿,膘,臕,蔈,藨,表,裱,褾,諘,謤,贆,錶,鏢,鑣,镖,镳,颮,颷,飆,飇,飈,飊,飑,飙,飚,驃,驫,骉,骠,髟,鰾,鳔,麃,㟽,㠒,㧼,㯱,㯹,䔸,䞄|fei:俷,剕,匪,厞,吠,啡,奜,妃,婓,婔,屝,废,廃,廢,悱,扉,斐,昲,暃,曊,朏,杮,棐,榧,櫠,沸,淝,渄,濷,狒,猆,疿,痱,癈,篚,緋,绯,翡,肥,肺,胐,腓,菲,萉,蕜,蕟,蜚,蜰,蟦,裶,誹,诽,費,费,鐨,镄,霏,靅,非,靟,飛,飝,飞,餥,馡,騑,騛,鯡,鲱,鼣,㔗,㥱,㩌,㭭,㵒,䆏,䈈,䉬,䑔,䕁,䕠,䚨,䛍,䠊,䤵,䨽,䨾,䰁|bei:俻,倍,偝,偹,備,僃,北,卑,喺,备,悖,悲,惫,愂,憊,揹,昁,杯,桮,梖,焙,牬,犕,狈,狽,珼,琲,盃,碑,碚,禙,糒,背,苝,蓓,藣,蛽,被,褙,誖,貝,贝,軰,輩,辈,邶,鄁,鉳,鋇,鐾,钡,陂,鞴,骳,鵯,鹎,㔨,㛝,㣁,㤳,㰆,㶔,㷶,㸢,㸬,㸽,㻗,㼎,㾱,䁅,䋳,䔒,䠙,䡶,䩀,䰽|zong:倊,倧,偬,傯,堫,宗,嵏,嵕,嵸,总,惣,惾,愡,捴,揔,搃,摠,昮,朡,棕,椶,熧,燪,猔,猣,疭,瘲,碂,磫,稯,粽,糉,綜,緃,総,緵,縂,縦,縱,總,纵,综,翪,腙,艐,葼,蓗,蝬,豵,踨,踪,蹤,錝,鍯,鏓,鑁,騌,騣,骔,鬃,鬉,鬷,鯮,鯼,㢔,㯶,㷓,㹅,䍟,䝋,䰌|tian:倎,兲,唺,塡,填,天,婖,屇,忝,恬,悿,捵,掭,搷,晪,殄,沺,淟,添,湉,琠,瑱,璳,甛,甜,田,畋,畑,畠,痶,盷,睓,睼,碵,磌,窴,緂,胋,腆,舔,舚,菾,覥,觍,賟,酟,錪,闐,阗,靔,靝,靦,餂,鴫,鷆,鷏,黇,㐁,㖭,㙉,㥏,㧂,㮇,㶺,䄼,䄽,䐌,䑚,䟧,䠄,䡒,䡘,䣯,䥖,䩄|dao:倒,刀,刂,到,叨,噵,壔,宲,导,導,屶,岛,島,嶋,嶌,嶹,忉,悼,捣,捯,搗,擣,朷,椡,槝,檤,氘,焘,燾,瓙,盗,盜,祷,禂,禱,稲,稻,纛,翢,翿,舠,菿,衜,衟,蹈,軇,道,釖,陦,隝,隯,魛,鱽,㠀,㿒,䆃,䌦,䧂,䲽|tan:倓,傝,僋,叹,啴,嗿,嘆,嘽,坍,坛,坦,埮,墰,墵,壇,壜,婒,弾,忐,怹,惔,憛,憳,憻,探,摊,撢,擹,攤,昙,暺,曇,榃,橝,檀,歎,毯,湠,滩,潬,潭,灘,炭,璮,痑,痰,瘫,癱,碳,罈,罎,舑,舕,菼,藫,袒,襢,覃,談,譚,譠,谈,谭,貚,貪,賧,贪,赕,郯,醈,醓,醰,鉭,錟,钽,锬,顃,鷤,㲜,㲭,㷋,㽑,䃪,䆱,䉡,䊤,䏙,䐺,䕊,䜖,䞡,䦔|chui:倕,吹,垂,埀,捶,搥,桘,棰,槌,炊,箠,腄,菙,錘,鎚,锤,陲,顀,龡,㓃,㝽,㥨,㩾,䄲,䍋,䞼,䳠|tang:倘,偒,傏,傥,儻,劏,唐,啺,嘡,坣,堂,塘,嵣,帑,戃,搪,摥,曭,棠,榶,樘,橖,汤,淌,湯,溏,漟,烫,煻,燙,爣,瑭,矘,磄,禟,篖,糃,糖,糛,羰,耥,膅,膛,蓎,薚,蝪,螗,螳,赯,趟,踼,蹚,躺,鄌,醣,鎕,鎲,鏜,鐋,钂,铴,镋,镗,闛,隚,鞺,餳,餹,饄,饧,鶶,鼞,㑽,㒉,㙶,㜍,㭻,㲥,㼺,㿩,䅯,䉎,䌅,䟖,䣘,䧜|kong:倥,埪,孔,崆,恐,悾,控,涳,硿,空,箜,躻,躼,錓,鞚,鵼,㤟,㸜|juan:倦,劵,勌,勬,卷,呟,埍,奆,姢,娟,帣,弮,慻,捐,捲,桊,涓,淃,狷,獧,瓹,眷,睊,睠,絭,絹,绢,罥,羂,脧,臇,菤,蔨,蠲,裐,鄄,鋑,鋗,錈,鎸,鐫,锩,镌,隽,雋,飬,餋,鵑,鹃,㢧,㢾,㪻,㯞,㷷,䄅,䌸,䖭,䚈,䡓,䳪|luo:倮,儸,剆,啰,囉,峈,捋,摞,攞,曪,椤,欏,泺,洛,洜,漯,濼,犖,猡,玀,珞,瘰,癳,砢,笿,箩,籮,絡,纙,络,罗,羅,脶,腡,臝,荦,萝,落,蓏,蘿,螺,蠃,裸,覶,覼,躶,逻,邏,鏍,鑼,锣,镙,雒,頱,饠,駱,騾,驘,骆,骡,鮥,鱳,鵅,鸁,㑩,㒩,㓢,㦬,㩡,㰁,㱻,㴖,㼈,㽋,㿚,䀩,䇔,䈷,䊨,䌱,䌴,䯁|song:倯,傱,凇,娀,宋,崧,嵩,嵷,庺,忪,怂,悚,愯,慫,憽,捒,松,枀,枩,柗,梥,檧,淞,濍,硹,竦,耸,聳,菘,蜙,訟,誦,讼,诵,送,鎹,頌,颂,餸,駷,鬆,㕬,㧐,㨦,㩳,㮸,䉥,䛦,䜬,䢠|leng:倰,冷,堎,塄,愣,棱,楞,睖,碐,稜,薐,踜,䉄,䚏,䬋,䮚|ben:倴,坌,奔,奙,捹,撪,本,桳,楍,泍,渀,犇,獖,畚,笨,苯,賁,贲,輽,逩,錛,锛,㡷,㤓,㨧,㮺,㱵,䬱|zhai:债,債,夈,宅,寨,捚,摘,斋,斎,斏,榸,瘵,砦,窄,粂,鉙,齋,㡯,㩟|qing:倾,傾,儬,凊,剠,勍,卿,圊,埥,夝,庆,庼,廎,情,慶,掅,擎,擏,晴,暒,棾,樈,檠,檾,櫦,殑,殸,氢,氫,氰,淸,清,漀,濪,甠,硘,碃,磬,箐,罄,苘,葝,蜻,請,謦,请,軽,輕,轻,郬,鑋,靑,青,靘,頃,顷,鯖,鲭,黥,㯳,㷫,䋜,䌠,䔛,䝼,䞍,䯧,䲔|ying:偀,僌,啨,営,嘤,噟,嚶,塋,婴,媖,媵,嫈,嬰,嬴,孆,孾,巆,巊,应,廮,影,応,愥,應,摬,撄,攍,攖,攚,映,暎,朠,桜,梬,楹,樱,櫻,櫿,浧,渶,溁,溋,滎,滢,潁,潆,濙,濚,濴,瀅,瀛,瀠,瀯,瀴,灐,灜,煐,熒,營,珱,瑛,瑩,璎,瓔,甇,甖,瘿,癭,盁,盈,矨,硬,碤,礯,穎,籝,籯,緓,縈,纓,绬,缨,罂,罃,罌,膡,膺,英,茔,荥,荧,莹,莺,萤,营,萦,萾,蓥,藀,蘡,蛍,蝇,蝧,蝿,螢,蠅,蠳,褮,覮,謍,譍,譻,賏,贏,赢,軈,迎,郢,鎣,鐛,鑍,锳,霙,鞕,韺,頴,颍,颕,颖,鴬,鶧,鶯,鷪,鷹,鸎,鸚,鹦,鹰,㑞,㢍,㨕,㯋,㲟,㴄,㵬,㶈,㹙,㹚,㿘,䀴,䁐,䁝,䃷,䇾,䑉,䕦,䙬,䤝,䨍,䪯,䭊,䭗|ruan:偄,堧,壖,媆,嫰,愞,撋,朊,瑌,瓀,碝,礝,緛,耎,腝,蝡,軟,輭,软,阮,㼱,㽭,䓴,䞂,䪭|chun:偆,唇,堾,媋,惷,旾,春,暙,杶,椿,槆,橁,櫄,浱,淳,湻,滣,漘,犉,瑃,睶,箺,純,纯,脣,莼,萅,萶,蒓,蓴,蝽,蠢,賰,踳,輴,醇,醕,錞,陙,鯙,鰆,鶉,鶞,鹑,㖺,㝄,㝇,㵮,㸪,㿤,䄝,䏛,䏝,䐇,䐏,䓐,䔚,䞐,䣨,䣩,䥎,䦮,䫃|ruo:偌,叒,婼,嵶,弱,挼,捼,楉,渃,焫,爇,箬,篛,若,蒻,鄀,鰙,鰯,鶸,䐞|pian:偏,囨,媥,楄,楩,片,犏,篇,翩,胼,腁,覑,諚,諞,谝,貵,賆,蹁,駢,騈,騗,騙,骈,骗,骿,魸,鶣,㓲,㛹,㸤,㼐,䏒,䮁|sheng:偗,剩,剰,勝,升,呏,圣,墭,声,嵊,憴,斘,昇,晟,晠,曻,枡,榺,橳,殅,泩,渑,渻,湦,澠,焺,牲,珄,琞,生,甥,盛,省,眚,竔,笙,縄,繩,绳,聖,聲,胜,苼,蕂,譝,貹,賸,鉎,鍟,阩,陞,陹,鱦,鵿,鼪,㗂,㼳,㾪,䁞,䎴,䚇,䞉,䪿,䱆|huang:偟,兤,凰,喤,堭,塃,墴,奛,媓,宺,崲,巟,幌,徨,怳,恍,惶,愰,慌,揘,晃,晄,曂,朚,楻,榥,櫎,湟,滉,潢,炾,煌,熀,熿,獚,瑝,璜,癀,皇,皝,皩,磺,穔,篁,簧,縨,肓,艎,荒,葟,蝗,蟥,衁,詤,諻,謊,谎,趪,遑,鍠,鎤,鐄,锽,隍,韹,餭,騜,鰉,鱑,鳇,鷬,黃,黄,㞷,㤺,㨪,㬻,㾠,㾮,䁜,䅣,䊗,䊣,䌙,䍿,䐠,䐵,䑟,䞹,䪄,䮲,䳨|duan:偳,塅,媏,断,斷,椴,段,毈,煅,瑖,短,碫,端,簖,籪,緞,缎,耑,腶,葮,褍,躖,鍛,鍴,锻,㫁,㱭,䠪|zan:偺,儧,儹,兂,咱,喒,囋,寁,撍,攒,攢,昝,暂,暫,濽,灒,瓉,瓒,瓚,禶,簪,簮,糌,襸,讃,讚,賛,贊,赞,趱,趲,蹔,鄼,酂,酇,錾,鏨,鐕,饡,㜺,㟛,㣅,㤰|lou:偻,僂,喽,嘍,塿,娄,婁,屚,嵝,嶁,廔,慺,搂,摟,楼,樓,溇,漊,漏,熡,甊,瘘,瘺,瘻,瞜,篓,簍,耧,耬,艛,蒌,蔞,蝼,螻,謱,軁,遱,鏤,镂,陋,鞻,髅,髏,㔷,㟺,㥪,㪹,㲎,㺏,䁖,䄛,䅹,䝏,䣚,䫫,䮫,䱾|sou:傁,凁,叜,叟,嗖,嗾,廀,廋,捜,搜,摗,擞,擻,櫢,溲,獀,瘶,瞍,艘,蒐,蓃,薮,藪,螋,鄋,醙,鎪,锼,颼,飕,餿,馊,騪,㖩,㛐,㵻,䈹,䉤,䏂,䮟|yuan:傆,元,冤,剈,原,厡,厵,员,員,噮,囦,园,圆,圎,園,圓,圜,垣,垸,塬,夗,妴,媛,媴,嫄,嬽,寃,弲,怨,悁,惌,愿,掾,援,杬,棩,榞,榬,橼,櫞,沅,淵,渁,渆,渊,渕,湲,源,溒,灁,爰,猨,猿,獂,瑗,盶,眢,禐,笎,箢,緣,縁,缘,羱,肙,苑,葾,蒝,蒬,薗,蚖,蜎,蜵,蝝,蝯,螈,衏,袁,裫,褑,褤,謜,貟,贠,轅,辕,远,逺,遠,邍,邧,酛,鈨,鋺,鎱,院,願,駌,騵,魭,鳶,鴛,鵷,鶢,鶰,鸢,鸳,鹓,黿,鼋,鼘,鼝,㟶,㤪,㥐,㥳,㭇,㹉,䅈,䏍,䖠,䛄,䛇,䩩,䬇,䬧,䬼,䲮,䳒,䳣|rong:傇,冗,媶,嫆,嬫,宂,容,峵,嵘,嵤,嶸,戎,搈,搑,摉,曧,栄,榕,榮,榵,毧,氄,溶,瀜,烿,熔,爃,狨,瑢,穁,穃,絨,縙,绒,羢,肜,茙,茸,荣,蓉,蝾,融,螎,蠑,褣,軵,鎔,镕,駥,髶,㘇,㝐,㣑,㭜,㲓,㲝,㲨,㺎,㼸,䇀,䇯,䈶,䘬,䠜,䡆,䡥,䢇,䤊,䩸|jiang:傋,僵,勥,匞,匠,壃,夅,奖,奨,奬,姜,将,將,嵹,弜,弶,彊,摪,摾,杢,桨,槳,橿,櫤,殭,江,洚,浆,滰,漿,犟,獎,畕,畺,疅,疆,礓,糡,糨,絳,繮,绛,缰,翞,耩,膙,茳,葁,蒋,蔣,薑,螀,螿,袶,講,謽,讲,豇,酱,醤,醬,降,韁,顜,鱂,鳉,㢡,㯍,䁰,䉃,䋌,䒂,䕭,䕯,䙹,䞪|bang:傍,垹,塝,峀,帮,幇,幚,幫,徬,捠,梆,棒,棓,榜,浜,牓,玤,硥,磅,稖,綁,縍,绑,膀,艕,蒡,蚌,蜯,謗,谤,邦,邫,鎊,镑,鞤,㔙,㭋,㮄,㯁,㾦,䂜,䎧,䖫,䟺,䧛,䰷|hao:傐,儫,兞,号,哠,嗥,嘷,噑,嚆,嚎,壕,好,恏,悎,昊,昦,晧,暤,暭,曍,椃,毫,浩,淏,滈,澔,濠,灏,灝,獆,獋,皓,皜,皞,皡,皥,秏,竓,籇,耗,聕,茠,蒿,薃,薅,薧,號,蚝,蠔,譹,豪,郝,顥,颢,鰝,㕺,㘪,㙱,㚪,㝀,㞻,㠙,㩝,㬔,㬶,㵆,䒵,䚽,䝞,䝥,䧫,䪽,䬉,䯫|shan:傓,僐,删,刪,剡,剼,善,嘇,圸,埏,墠,墡,姍,姗,嬗,山,幓,彡,扇,挻,搧,擅,敾,晱,曑,杉,杣,椫,樿,檆,汕,潸,澘,灗,炶,烻,煔,煽,熌,狦,珊,疝,痁,睒,磰,笘,縿,繕,缮,羴,羶,脠,膳,膻,舢,芟,苫,蔪,蟮,蟺,衫,覢,訕,謆,譱,讪,贍,赡,赸,跚,軕,邖,鄯,釤,銏,鐥,钐,閃,閊,闪,陕,陝,饍,騸,骟,鯅,鱓,鱔,鳝,㚒,㣌,㣣,㨛,㪎,㪨,㶒,䄠,䆄,䚲,䠾,䥇,䦂,䦅,䱇,䱉,䴮|suo:傞,唆,唢,嗦,嗩,娑,惢,所,挲,摍,暛,桫,梭,溑,溹,琐,琑,瑣,睃,簑,簔,索,縮,缩,羧,莏,蓑,蜶,趖,逤,鎍,鎖,鎻,鎼,鏁,锁,髿,鮻,㪽,䂹,䅴,䈗,䐝,䖛,䗢,䞆,䞽,䣔,䵀|zai:傤,儎,再,哉,在,宰,崽,扗,栽,洅,渽,溨,災,灾,烖,甾,睵,縡,菑,賳,載,载,酨,㞨,㱰,㴓,䏁,䣬,䮨,䵧|bin:傧,儐,宾,彬,摈,擯,斌,椕,槟,殡,殯,氞,汃,滨,濒,濱,濵,瀕,瑸,璸,砏,繽,缤,膑,臏,虨,蠙,豩,豳,賓,賔,邠,鑌,镔,霦,顮,髌,髕,髩,鬂,鬓,鬢,䐔|nuo:傩,儺,喏,懦,懧,挪,掿,搦,搻,桛,梛,榒,橠,燶,硸,稬,穤,糑,糥,糯,諾,诺,蹃,逽,郍,鍩,锘,黁,㐡,㑚,㔮,㛂,㡅,㰙,䚥|can:傪,儏,参,參,叄,叅,喰,噆,嬠,惨,惭,慘,慙,慚,憯,朁,残,殘,湌,澯,灿,燦,爘,璨,穇,粲,薒,蚕,蝅,蠶,蠺,謲,飡,餐,驂,骖,黪,黲,㘔,㛑,㜗,㣓,㥇,㦧,㨻,㱚,㺑,㻮,㽩,㿊,䅟,䍼,䏼,䑶,䗝,䗞,䘉,䙁,䛹,䝳,䣟,䫮,䬫,䳻|lei:傫,儡,儽,厽,嘞,垒,塁,壘,壨,嫘,擂,攂,樏,檑,櫐,櫑,欙,泪,洡,涙,淚,灅,瓃,畾,癗,矋,磊,磥,礌,礧,礨,禷,类,累,絫,縲,纇,纍,纝,缧,罍,羸,耒,肋,脷,蔂,蕌,蕾,藟,蘱,蘲,蘽,虆,蠝,誄,讄,诔,轠,酹,銇,錑,鐳,鑘,鑸,镭,雷,靁,頛,頪,類,颣,鱩,鸓,鼺,㑍,㒍,㒦,㔣,㙼,㡞,㭩,㲕,㴃,㵢,㶟,㹎,㼍,㿔,䉂,䉓,䉪,䍣,䍥,䐯,䒹,䛶,䢮,䣂,䣦,䨓,䮑,䴎|zao:傮,凿,唕,唣,喿,噪,慥,早,枣,栆,梍,棗,澡,灶,煰,燥,璅,璪,皁,皂,竃,竈,簉,糟,艁,薻,藻,蚤,譟,趮,蹧,躁,造,遭,醩,鑿,㲧,㿷,䜊,䥣,䲃|ao:傲,凹,厫,嗷,嗸,坳,垇,墺,奡,奥,奧,媪,媼,嫯,岙,岰,嶅,嶴,廒,慠,懊,扷,抝,拗,摮,擙,敖,柪,滶,澚,澳,熬,爊,獒,獓,璈,磝,翱,翶,翺,聱,芺,蔜,螯,袄,襖,謷,謸,軪,遨,鏊,鏖,镺,隞,驁,骜,鰲,鳌,鷔,鼇,㑃,㕭,㘬,㘭,㜜,㜩,㟼,㠂,㠗,㤇,㥿,㿰,䁱,䐿,䚫,䜒,䞝,䥝,䦋,䫨,䮯,䯠,䴈,䵅|chuang:傸,刅,创,刱,剏,剙,創,噇,幢,床,怆,愴,摐,漺,牀,牎,牕,疮,瘡,磢,窓,窗,窻,闖,闯,㡖,㵂,䃥,䆫,䇬,䎫,䚒,䡴,䭚|piao:僄,剽,勡,嘌,嫖,彯,徱,慓,旚,殍,漂,犥,瓢,皫,瞟,磦,票,篻,縹,缥,翲,薸,螵,醥,闝,顠,飃,飄,飘,魒,㩠,㬓,㵱,㹾,㺓,㼼,䏇,䴩|man:僈,墁,姏,嫚,屘,幔,悗,慢,慲,摱,曼,槾,樠,満,满,滿,漫,澫,澷,熳,獌,睌,瞒,瞞,矕,縵,缦,蔄,蔓,蘰,蛮,螨,蟃,蟎,蠻,襔,謾,谩,鄤,鏋,鏝,镘,鞔,顢,颟,饅,馒,鬗,鬘,鰻,鳗,㒼,㗄,㗈,㙢,㛧,㡢,㬅,㵘,䅼,䊡,䐽,䑱,䕕,䛲,䜱,䝡,䝢,䟂,䡬,䯶,䰋|zun:僔,噂,尊,嶟,捘,撙,樽,繜,罇,譐,遵,銌,鐏,鱒,鳟,鶎,鷷|deng:僜,凳,噔,墱,嬁,嶝,戥,櫈,灯,燈,璒,登,瞪,磴,竳,等,簦,艠,覴,豋,蹬,邓,鄧,鐙,镫,隥,䃶,䒭,䠬,䮴|tie:僣,呫,帖,怗,聑,萜,蛈,貼,贴,跕,鉄,銕,鐡,鐢,鐵,铁,飻,餮,驖,鴩,䥫,䴴,䵿|seng:僧|min:僶,冧,冺,刡,勄,垊,姄,岷,崏,忞,怋,悯,愍,慜,憫,抿,捪,敃,敏,敯,旻,旼,暋,民,泯,湣,潣,玟,珉,琘,琝,瑉,痻,皿,盿,碈,笢,笽,簢,緍,緡,缗,罠,苠,蠠,賯,鈱,錉,鍲,閔,閩,闵,闽,鰵,鳘,鴖,黽,㞶,㟩,㟭,㢯,㥸,㨉,䁕,䂥,䃉,䋋,䟨,䡅,䡑,䡻,䪸,䲄|sai:僿,嗮,嘥,噻,塞,愢,揌,毢,毸,簺,腮,虄,賽,赛,顋,鰓,鳃,㗷,䈢|dang:儅,党,凼,噹,圵,垱,壋,婸,宕,当,挡,擋,攩,档,檔,欓,氹,潒,澢,灙,珰,璗,璫,瓽,當,盪,瞊,砀,碭,礑,筜,簜,簹,艡,荡,菪,蕩,蘯,蟷,裆,襠,譡,讜,谠,趤,逿,闣,雼,黨,䑗,䣊,䣣,䦒|xuan:儇,吅,咺,喧,塇,媗,嫙,嬛,宣,怰,悬,愃,愋,懸,揎,旋,昍,昡,晅,暄,暅,暶,梋,楥,楦,檈,泫,渲,漩,炫,烜,煊,玄,玹,琁,琄,瑄,璇,璿,痃,癣,癬,眩,眴,睻,矎,碹,禤,箮,絢,縼,繏,绚,翧,翾,萱,萲,蓒,蔙,蕿,藼,蘐,蜁,蝖,蠉,衒,袨,諠,諼,譞,讂,谖,贙,軒,轩,选,選,鉉,鍹,鏇,铉,镟,鞙,颴,駽,鰚,㘣,㧦,㳙,㳬,㹡,㾌,䁢,䍗,䍻,䗠,䘩,䝮,䠣,䧎,䩙,䩰,䮄,䲂,䲻,䴉,䴋|tai:儓,冭,台,囼,坮,太,夳,嬯,孡,忲,态,態,抬,擡,旲,檯,汰,泰,溙,炱,炲,燤,珆,箈,籉,粏,肽,胎,臺,舦,苔,菭,薹,跆,邰,酞,鈦,钛,颱,駘,骀,鮐,鲐,㑷,㒗,㘆,㙵,㣍,㥭,㬃,㷘,㸀,䈚,䑓,䢰,䣭|lan:儖,兰,厱,嚂,囒,壈,壏,婪,嬾,孄,孏,岚,嵐,幱,懒,懢,懶,拦,揽,擥,攔,攬,斓,斕,栏,榄,欄,欖,欗,浨,滥,漤,澜,濫,瀾,灆,灠,灡,烂,燗,燣,爁,爛,爤,爦,璼,瓓,礷,篮,籃,籣,糷,繿,纜,缆,罱,葻,蓝,蓞,藍,蘭,褴,襕,襤,襴,襽,覧,覽,览,譋,讕,谰,躝,醂,鑭,钄,镧,闌,阑,韊,㑣,㘓,㛦,㜮,㞩,㦨,㨫,㩜,㰖,㱫,㳕,䃹,䆾,䊖,䌫,䍀,䑌,䦨,䪍,䰐,䳿|meng:儚,冡,勐,夢,夣,孟,幪,庬,懜,懞,懵,掹,擝,曚,朦,梦,橗,檬,氋,溕,濛,猛,獴,瓾,甍,甿,盟,瞢,矇,矒,礞,罞,艋,艨,莔,萌,萠,蒙,蕄,虻,蜢,蝱,蠓,鄳,鄸,錳,锰,雺,霥,霿,靀,顭,饛,鯍,鯭,鸏,鹲,鼆,㙹,㚞,㜴,㝱,㠓,㩚,䀄,䇇,䉚,䏵,䑃,䑅,䒐,䓝,䗈,䙦,䙩,䠢,䤓,䥂,䥰,䰒,䲛,䴌,䴿,䵆|qiong:儝,卭,宆,惸,憌,桏,橩,焪,焭,煢,熍,琼,璚,瓊,瓗,睘,瞏,穷,穹,窮,竆,笻,筇,舼,茕,藑,藭,蛩,蛬,赹,跫,邛,銎,㒌,㧭,㮪,㷀,㼇,䅃,䆳,䊄,䓖,䛪,䠻|lie:儠,冽,列,劣,劽,咧,埒,埓,姴,峢,巤,挒,挘,捩,擸,毟,洌,浖,烈,烮,煭,犣,猎,猟,獵,睙,聗,脟,茢,蛚,裂,趔,躐,迾,颲,鬛,鬣,鮤,鱲,鴷,㤠,㧜,㬯,㭞,㯿,㲱,㸹,㼲,㽟,䁽,䅀,䉭,䓟,䜲,䟩,䟹,䢪,䴕|kuang:儣,况,劻,匡,匩,哐,圹,壙,夼,岲,恇,懬,懭,抂,旷,昿,曠,框,況,洭,爌,狂,狅,眖,眶,矌,矿,砿,礦,穬,筐,筺,絋,絖,纊,纩,誆,誑,诓,诳,貺,贶,軖,軠,軦,軭,邝,邼,鄺,鉱,鋛,鑛,鵟,黋,㤮,䊯,䵃|chen:儭,嗔,嚫,塵,墋,夦,宸,尘,忱,愖,抻,揨,敐,晨,曟,棽,榇,樄,櫬,沉,烥,煁,琛,疢,瘎,瞋,硶,碜,磣,稱,綝,臣,茞,莀,莐,蔯,薼,螴,衬,襯,訦,諃,諶,謓,讖,谌,谶,賝,贂,趁,趂,趻,踸,軙,辰,迧,郴,鈂,陈,陳,霃,鷐,麎,齓,齔,龀,㕴,㧱,㫳,㲀,㴴,㽸,䆣,䒞,䚘,䜟,䞋,䟢,䢅,䢈,䢻,䣅,䤟,䫖|teng:儯,唞,幐,朰,滕,漛,疼,痋,籐,籘,縢,腾,膯,藤,虅,螣,誊,謄,邆,霯,駦,騰,驣,鰧,鼟,䒅,䕨,䠮,䲍,䲢|long:儱,咙,哢,嚨,垄,垅,壟,壠,屸,嶐,巃,巄,徿,拢,攏,昽,曨,朧,栊,梇,槞,櫳,泷,湰,漋,瀧,爖,珑,瓏,癃,眬,矓,砻,硦,礱,礲,窿,竉,竜,笼,篭,籠,聋,聾,胧,茏,蕯,蘢,蠪,蠬,衖,襱,豅,贚,躘,鏧,鑨,陇,隆,隴,霳,靇,驡,鸗,龍,龒,龓,龙,㑝,㙙,㚅,㛞,㝫,㟖,㡣,㢅,㦕,㰍,㴳,䃧,䏊,䙪,䡁,䥢,䪊|rang:儴,勷,嚷,壌,壤,懹,攘,瀼,爙,獽,瓤,禳,穣,穰,纕,蘘,譲,讓,让,躟,鬤,㚂,䉴|xiong:兄,兇,凶,匈,哅,夐,忷,恟,敻,汹,洶,熊,胷,胸,芎,訩,詗,詾,讻,诇,雄,㐫,䧺|chong:充,冲,嘃,埫,宠,寵,崇,崈,徸,忡,憃,憧,揰,摏,沖,浺,漴,爞,珫,緟,罿,翀,舂,艟,茺,虫,蝩,蟲,衝,褈,蹖,銃,铳,隀,㓽,㧤,㹐,䌬,䖝,䳯|dui:兊,兌,兑,叾,垖,堆,塠,对,対,對,嵟,怼,憝,懟,濧,瀩,痽,碓,磓,祋,綐,薱,譈,譵,鐓,鐜,镦,队,陮,隊,頧,鴭,㙂,㟋,㠚,㬣,㳔,㵽,䇏,䇤,䔪,䨴,䨺,䬈,䬽,䯟|ke:克,刻,剋,勀,勊,匼,可,咳,嗑,坷,堁,壳,娔,客,尅,岢,峇,嵑,嵙,嶱,恪,愙,揢,搕,敤,柯,棵,榼,樖,殻,氪,渇,渴,溘,炣,牁,犐,珂,疴,痾,瞌,碦,磕,礊,礚,科,稞,窠,緙,缂,翗,胢,苛,萪,薖,蝌,課,课,趷,軻,轲,醘,鈳,錁,钶,锞,頦,顆,颏,颗,騍,骒,髁,㕉,㞹,㤩,㪃,㪙,㪡,㪼,㰤,㵣,㾧,䙐,䶗|tu:兎,兔,凃,凸,吐,唋,図,图,圖,圗,土,圡,堍,堗,塗,屠,峹,嵞,嶀,庩,廜,徒,怢,悇,捈,捸,揬,梌,汢,涂,涋,湥,潳,痜,瘏,禿,秃,稌,突,筡,腯,荼,莵,菟,葖,蒤,跿,迌,途,酴,釷,鈯,鋵,鍎,钍,馟,駼,鵌,鵚,鵵,鶟,鷋,鷵,鼵,㭸,㻌,㻠,㻬,㻯,䅷,䖘,䠈,䣄,䣝,䤅,䳜|qiang:兛,呛,唴,嗆,嗴,墏,墙,墻,嫱,嬙,嶈,廧,強,强,戕,戗,戧,抢,搶,摤,斨,枪,椌,槍,樯,檣,溬,漒,炝,熗,牄,牆,猐,獇,玱,琷,瑲,瓩,篬,繈,繦,羌,羗,羟,羥,羫,羻,腔,艢,蔃,蔷,薔,蘠,蜣,襁,謒,跄,蹌,蹡,錆,鎗,鏘,鏹,锖,锵,镪,㛨,㩖,䅚,䵁|nei:內,内,娞,氝,焾,腇,餒,馁,鮾,鯘,㕯,㖏,㘨,㨅,㼏,䡾,䲎,䳖|liu:六,刘,劉,嚠,囖,塯,媹,嬼,嵧,廇,懰,旈,旒,柳,栁,桞,桺,榴,橊,橮,沠,流,浏,溜,澑,瀏,熘,熮,珋,琉,瑠,瑬,璢,瓼,甅,畄,留,畱,疁,瘤,癅,硫,磂,磟,綹,绺,罶,羀,翏,蒥,蓅,藰,蟉,裗,蹓,遛,鋶,鎏,鎦,鏐,鐂,锍,镏,镠,雡,霤,飀,飂,飅,飗,餾,馏,駠,駵,騮,驑,骝,鬸,鰡,鶹,鷚,鹠,鹨,麍,㐬,㙀,㨨,㶯,㽌,㽞,䄂,䉧,䋷,䗜,䚧,䬟,䭷,䰘,䱖,䱞,䶉|pou:兺,咅,哛,哣,堷,婄,抔,抙,捊,掊,犃,箁,裒,颒,㕻,㧵|shou:兽,収,受,售,垨,壽,夀,守,寿,手,扌,授,收,涭,狩,獣,獸,痩,瘦,綬,绶,膄,艏,鏉,首,㖟,㝊,㥅,䛵,䭭|mao:冃,冇,冐,冒,卯,唜,堥,夘,媢,峁,帽,愗,懋,戼,旄,昴,暓,枆,楙,毛,毜,毝,毷,泖,渵,牦,猫,瑁,皃,眊,瞀,矛,笷,緢,耄,芼,茂,茅,茆,蓩,蛑,蝐,蝥,蟊,袤,覒,貌,貓,貿,贸,軞,鄚,鄮,酕,鉚,錨,铆,锚,髦,髳,鶜,㒵,㒻,㚹,㝟,㡌,㧇,㧌,㪞,㫯,㮘,㲠,㴘,㺺,㿞,䀤,䅦,䋃,䓮,䡚,䫉|ran:冄,冉,呥,嘫,姌,媣,染,橪,然,燃,珃,繎,肰,苒,蒅,蚦,蚺,衻,袇,袡,髥,髯,㚩,㜣,㯗,㲯,㸐,㾆,㿵,䎃,䑙,䒣,䖄,䡮,䣸,䤡,䫇|gang:冈,冮,刚,剛,堈,堽,岗,岡,崗,戆,戇,掆,杠,棡,槓,港,焵,牨,犅,疘,矼,筻,綱,纲,缸,罁,罓,罡,肛,釭,鋼,鎠,钢,阬,㟠,㟵,㽘,䴚|gua:冎,刮,剐,剮,劀,卦,叧,呱,啩,坬,寡,挂,掛,歄,焻,煱,瓜,絓,緺,罣,罫,胍,苽,褂,詿,诖,趏,銽,颪,颳,騧,鴰,鸹,㒷,䈑|kou:冦,剾,劶,口,叩,宼,寇,廤,彄,怐,扣,抠,摳,敂,滱,眍,瞉,瞘,窛,筘,簆,芤,蔲,蔻,釦,鷇,㓂,㔚,㰯,㲄,㽛,䳟,䳹|pan:冸,判,叛,坢,媻,幋,搫,攀,柈,槃,沜,泮,溿,潘,瀊,炍,爿,牉,畔,畨,盘,盤,盼,眅,磐,縏,蒰,蟠,袢,襻,詊,跘,蹒,蹣,鋬,鎜,鑻,鞶,頖,鵥,㐴,㳪,䃑,䃲,䈲,䰉,䰔|qia:冾,圶,帢,恰,愘,拤,掐,殎,洽,硈,葜,跒,酠,鞐,髂,㓣,㡊,㤉,䜑,䠍,䨐,䯊,䶝|mei:凂,呅,嚜,堳,塺,妹,媄,媒,媚,媺,嬍,寐,嵄,嵋,徾,抺,挴,攗,攟,昧,枚,栂,梅,楣,楳,槑,毎,每,沒,没,沬,浼,渼,湄,湈,煝,煤,燘,猸,玫,珻,瑂,痗,眉,眛,睂,睸,矀,祙,禖,篃,美,脄,脢,腜,苺,莓,葿,蘪,蝞,袂,跊,躾,郿,酶,鋂,鎂,鎇,镁,镅,霉,韎,鬽,魅,鶥,鹛,黣,黴,㭑,㶬,㺳,䀛,䆀,䉋,䊈,䊊,䍙,䒽,䓺,䜸,䤂,䰨,䰪,䵢|zhun:准,凖,埻,宒,準,稕,窀,綧,肫,衠,訰,諄,谆,迍|cou:凑,楱,湊,腠,輳,辏,㫶|du:凟,剢,匵,厾,嘟,堵,妒,妬,嬻,帾,度,杜,椟,櫝,殬,殰,毒,涜,渎,渡,瀆,牍,牘,犊,犢,独,獨,琽,瓄,皾,督,睹,秺,笃,篤,肚,芏,荰,蝳,螙,蠧,蠹,裻,覩,読,讀,讟,读,豄,賭,贕,赌,都,醏,錖,鍍,鑟,镀,闍,阇,靯,韇,韣,韥,騳,髑,黩,黷,㱩,㸿,㾄,䀾,䄍,䅊,䈞,䐗,䓯,䙱,䟻,䢱,䪅,䫳,䮷,䲧|cun:刌,吋,墫,存,寸,忖,拵,村,澊,皴,竴,籿,踆,邨,䍎|wen:刎,吻,呚,呡,問,塭,妏,彣,忟,抆,揾,搵,文,桽,榅,榲,殟,汶,渂,温,溫,炆,珳,瑥,璺,瘒,瘟,砇,稳,穏,穩,紊,紋,絻,纹,聞,肳,脕,脗,芠,莬,蚉,蚊,螡,蟁,豱,輼,轀,辒,鈫,鎾,閺,閿,闅,闦,闧,问,闻,阌,雯,顐,饂,馼,魰,鰛,鰮,鳁,鳼,鴍,鼤,㒚,㖧,㗃,㝧,㳷,䎹,䎽,䘇,䰚|hua:划,劃,化,华,哗,嘩,埖,姡,婲,婳,嫿,嬅,崋,摦,撶,杹,桦,椛,槬,樺,滑,澅,猾,璍,画,畫,畵,硴,磆,糀,繣,舙,花,芲,華,蕐,蘤,蘳,螖,觟,話,誮,諙,諣,譁,话,鋘,錵,鏵,铧,驊,骅,鷨,黊,㓰,㕦,㕲,㕷,㚌,㟆,㠏,㠢,㦊,㦎,㩇,㭉,㮯,䅿,䏦,䔢,䛡,䠉,䱻,䶤|yue:刖,嬳,岄,岳,嶽,彟,彠,恱,悅,悦,戉,抈,捳,曰,曱,月,枂,樾,汋,瀹,爚,玥,矱,礿,禴,箹,篗,籆,籥,籰,粤,粵,約,约,蘥,蚎,蚏,越,跀,跃,躍,軏,鈅,鉞,钥,钺,閱,閲,阅,鸑,鸙,黦,龠,龥,㜧,㜰,㬦,㰛,㹊,䋐,䖃,䟠,䠯,䡇,䢁,䢲,䤦,䥃,䶳|bie:別,别,咇,彆,徶,憋,瘪,癟,莂,虌,蛂,蟞,襒,蹩,鱉,鳖,鼈,龞,㢼,㿜,䉲,䋢,䏟,䠥,䭱|pao:刨,匏,咆,垉,奅,庖,抛,拋,泡,炮,炰,爮,狍,疱,皰,砲,礟,礮,脬,萢,蚫,袍,褜,跑,軳,鞄,麅,麭,㘐,㚿,㯡,䛌,䩝,䶌|shua:刷,唰,耍,誜|cuo:剉,剒,厝,夎,嵯,嵳,挫,措,搓,撮,棤,瑳,痤,睉,矬,磋,脞,莝,莡,蒫,蓌,蔖,虘,蹉,逪,遳,醝,銼,錯,锉,错,髊,鹺,鹾,齹,㟇,㽨,䂳,䐣,䟶,䠡,䣜,䱜,䴾|la:剌,啦,喇,嚹,垃,拉,揦,揧,搚,攋,旯,柆,楋,櫴,溂,爉,瓎,瘌,砬,磖,翋,腊,臈,臘,菈,藞,蜡,蝋,蝲,蠟,辢,辣,邋,鑞,镴,鞡,鬎,鯻,㕇,㸊,㻋,㻝,䂰,䃳,䏀,䓥,䗶,䝓,䟑,䪉,䱫,䶛|po:剖,叵,哱,嘙,坡,奤,娝,婆,尀,岥,岶,廹,敀,昢,櫇,泼,洦,溌,潑,烞,珀,皤,破,砶,笸,粕,蒪,蔢,謈,迫,鄱,酦,醱,釙,鉕,鏺,钋,钷,頗,颇,駊,魄,㛘,㨇,㰴,䄸,䎊,䞟,䣪,䣮,䨰,䪖,䯙|tuan:剬,剸,团,団,圕,團,塼,彖,慱,抟,摶,槫,檲,湍,湪,漙,煓,猯,疃,篿,糰,褖,貒,鏄,鷒,鷻,㩛,䊜,䜝,䵯|zuan:劗,揝,攥,籫,繤,纂,纉,纘,缵,躜,躦,鑚,鑽,钻,䂎,䌣,䎱,䤸|shao:劭,勺,卲,哨,娋,少,弰,捎,旓,柖,梢,潲,烧,焼,焽,燒,玿,稍,筲,紹,綤,绍,艄,芍,苕,莦,萔,蕱,蛸,袑,輎,邵,韶,颵,髾,鮹,㪢,㲈,㷹,㸛,䏴,䒚,䔠,䙼,䬰|gao:勂,吿,告,夰,峼,搞,暠,杲,槀,槁,槔,槹,橰,檺,櫜,滜,獔,皋,皐,睪,睾,祮,祰,禞,稁,稾,稿,筶,篙,糕,縞,缟,羔,羙,膏,臯,菒,藁,藳,誥,诰,郜,鋯,鎬,锆,镐,韟,餻,高,髙,鷎,鷱,鼛,㚏,㚖,㾸,䗣|lang:勆,唥,啷,埌,塱,嫏,崀,廊,悢,朖,朗,朤,桹,榔,樃,欴,浪,烺,狼,琅,瑯,硠,稂,筤,艆,莨,蒗,蓈,蓢,蜋,螂,誏,躴,郎,郒,郞,鋃,鎯,锒,閬,阆,駺,㓪,㙟,㝗,㟍,㢃,㫰,㮾,㱢,㾗,㾿,䀶,䁁,䆡,䍚,䕞,䡙,䯖,䱶|weng:勜,嗡,塕,奣,嵡,暡,滃,瓮,甕,瞈,罋,翁,聬,蓊,蕹,螉,鎓,鶲,鹟,齆,㘢,㜲,䐥,䤰|mang:匁,厖,吂,哤,壾,娏,尨,忙,恾,杗,杧,氓,汒,浝,漭,牤,牻,狵,痝,盲,硭,笀,芒,茫,茻,莽,莾,蘉,蛖,蟒,蠎,邙,釯,鋩,铓,駹,㙁,㝑,㟌,㟐,㟿,㡛,㬒,㻊,䀮,䁳,䅒,䈍,䒎,䖟,䟥,䵨|nao:匘,呶,垴,堖,夒,婥,嫐,孬,峱,嶩,巎,怓,恼,悩,惱,挠,撓,檂,淖,猱,獶,獿,瑙,硇,碙,碯,脑,脳,腦,臑,蛲,蟯,詉,譊,鐃,铙,閙,闹,鬧,㑎,㛴,㞪,㺀,㺁,䃩,䄩,䑋,䛝,䜀,䜧,䫸,䴃|za:匝,咂,囐,帀,拶,杂,桚,沞,沯,砸,磼,紥,紮,臜,臢,襍,鉔,雑,雜,雥,韴,魳,䕹,䞙,䪞|suan:匴,狻,痠,祘,笇,筭,算,蒜,酸,㔯|nian:卄,哖,埝,姩,年,廿,念,拈,捻,撚,撵,攆,涊,淰,碾,秊,秥,簐,艌,蔫,蹨,躎,輦,辇,鮎,鯰,鲇,鲶,鵇,黏,㘝,㞋,㲽,䄭,䄹,䚓,䩞,䬯|shuai:卛,帅,帥,摔,甩,蟀,衰,䢦|que:却,卻,埆,塙,墧,崅,悫,愨,慤,搉,榷,毃,炔,燩,瘸,皵,硞,确,碏,確,礐,礭,缺,舃,蒛,趞,闋,闕,阕,阙,雀,鵲,鹊,㕁,㩁,㰌,㱋,㱿,㴶,㾡,䇎,䦬,䧿|zhe:厇,哲,啠,喆,嗻,嚞,埑,嫬,悊,折,摺,晢,晣,柘,棏,樀,樜,歽,浙,淛,矺,砓,磔,籷,粍,者,蔗,虴,蛰,蜇,蟄,蟅,袩,褶,襵,詟,謫,謺,讁,讋,谪,赭,輒,輙,轍,辄,辙,这,這,遮,銸,鍺,锗,鮿,鷓,鹧,㞏,㪿,㯰,䂞,䊞,䎲,䏳,䐑,䐲,䓆,䗪,䝃,䝕,䠦,䩾,䵭|a:厑,吖,啊,嗄,錒,锕,阿|zui:厜,嗺,嘴,噿,嶊,嶵,晬,最,朘,枠,栬,樶,檇,檌,欈,濢,璻,祽,穝,絊,纗,罪,蕞,蟕,辠,酔,酻,醉,鋷,錊,㝡,㠑,㰎,䘹,䮔|rou:厹,媃,宍,揉,柔,楺,渘,煣,瑈,瓇,禸,粈,糅,肉,腬,葇,蝚,蹂,輮,鍒,鞣,韖,騥,鰇,鶔,㖻,㽥,䄾,䐓,䧷,䰆|shuang:双,塽,孀,孇,慡,樉,欆,滝,灀,爽,礵,縔,艭,鏯,雙,霜,騻,驦,骦,鷞,鸘,鹴,㦼,㼽,䗮,䡯,䫪|die:叠,哋,啑,喋,嚸,垤,堞,峌,嵽,幉,恎,惵,戜,挕,揲,昳,曡,曢,殜,氎,爹,牃,牒,瓞,畳,疂,疉,疊,眣,眰,碟,絰,绖,耊,耋,胅,臷,艓,苵,蜨,蝶,褋,褺,詄,諜,谍,趃,跌,蹀,迭,镻,鰈,鲽,㑙,㥈,㦶,㩸,㩹,㫼,㬪,㭯,㲲,㲳,㷸,㻡,䘭,䞇,䞕,䠟,䪥,䮢,䲀,䳀,䴑|rui:叡,壡,枘,桵,橤,汭,瑞,甤,睿,緌,繠,芮,蕊,蕋,蕤,蘂,蘃,蚋,蜹,銳,鋭,锐,㓹,㛱,㪫,㮃,㲊,䅑,䌼,䓲|tun:吞,呑,啍,坉,屯,忳,旽,暾,朜,氽,涒,焞,畽,臀,臋,芚,豘,豚,軘,霕,飩,饨,魨,鲀,黗,㖔,㞘,㩔,㹠,㼊|fou:否,垺,妚,紑,缶,缹,缻,雬,鴀,䳕|shun:吮,瞬,舜,顺,㥧,䀢,䀵,䑞|guo:呙,咼,啯,嘓,囯,囶,囻,国,圀,國,埚,堝,墎,崞,帼,幗,彉,彍,惈,慖,掴,摑,果,椁,楇,槨,淉,漍,濄,猓,瘑,粿,綶,聒,聝,腂,腘,膕,菓,蔮,虢,蜾,蝈,蟈,裹,褁,輠,过,過,郭,鈛,鍋,鐹,锅,餜,馃,馘,㕵,㖪,㚍,㞅,㳀,㶁,䂸,䆐,䐸,䙨,䤋,䬎,䴹|pen:呠,喯,喷,噴,歕,湓,濆,瓫,盆,翉,翸,葐|ne:呢,抐,疒,眲,訥,讷,䎪,䭆|m:呣,嘸|huai:咶,坏,壊,壞,徊,怀,懐,懷,槐,櫰,淮,瀤,耲,蘹,蘾,褢,褱,踝,㜳,䈭,䴜|pin:品,嚬,姘,娉,嫔,嬪,拼,朩,榀,汖,牝,玭,琕,矉,礗,穦,聘,薲,貧,贫,頻,顰,频,颦,馪,驞,㰋,䀻|yo:哟,唷,喲|o:哦|shui:哾,帨,楯,橓,水,氵,氺,涗,涚,睡,瞚,瞤,祱,稅,税,脽,蕣,裞,說,説,誰,谁,閖,順,鬊,㽷,䭨|huan:唤,喚,喛,嚾,堚,奂,奐,宦,寏,寰,峘,嵈,幻,患,愌,懁,懽,换,換,擐,攌,桓,梙,槵,欢,欥,歓,歡,洹,浣,涣,渙,漶,澣,澴,烉,焕,煥,狟,獾,环,瑍,環,瓛,痪,瘓,睆,瞣,糫,絙,綄,緩,繯,缓,缳,羦,肒,荁,萈,萑,藧,讙,豢,豲,貆,貛,輐,轘,还,逭,還,郇,酄,鍰,鐶,锾,镮,闤,阛,雈,驩,鬟,鯇,鯶,鰀,鲩,鴅,鵍,鹮,㓉,㕕,㡲,㣪,㦥,㪱,㬇,㬊,㵹,㶎,㹖,㼫,㿪,䀓,䀨,䆠,䈠,䍺,䝠,䥧,䦡,䭴,䮝,䯘,䴟|nou:啂,槈,檽,獳,羺,耨,譨,譳,鎒,鐞,㝹,䅶,䘫,䨲,䰭|ken:啃,垦,墾,恳,懇,掯,肎,肯,肻,裉,褃,豤,貇,錹,㸧|chuai:啜,嘬,揣,膗,踹,㪓,㪜,䦟,䦤,䦷|pa:啪,妑,帊,帕,怕,掱,杷,潖,爬,琶,皅,筢,舥,葩,袙,趴,䯲,䶕|se:啬,嗇,懎,擌,栜,槮,歮,歰,洓,涩,渋,澀,澁,濇,濏,瀒,琗,瑟,璱,瘷,穑,穡,穯,篸,縇,繬,聓,色,裇,襂,譅,轖,銫,鏼,铯,閪,雭,飋,鬙,㒊,㥶,㮦,㱇,㴔,㻭,䉢,䔼,䨛|nie:啮,喦,嗫,噛,嚙,囁,囓,圼,孼,孽,嵲,嶭,巕,帇,惗,捏,揑,摰,敜,枿,槷,櫱,涅,篞,籋,糱,糵,聂,聶,肀,臬,臲,苶,菍,蘖,蠥,讘,踂,踗,踙,蹑,躡,鉩,錜,鎳,鑷,钀,镊,镍,闑,陧,隉,顳,颞,齧,㖖,㘿,㙞,㚔,㜸,㡪,㩶,㮆,㴪,㸎,䂼,䄒,䌜,䜓,䯀,䯅,䯵|n:啱,嗯,莻,鈪,銰,㐻|wai:喎,外,崴,歪,竵,顡,㖞,䠿|miao:喵,妙,媌,嫹,庙,庿,廟,描,杪,淼,渺,玅,眇,瞄,秒,竗,篎,緲,缈,苗,藐,邈,鱙,鶓,鹋,㑤,㠺,㦝,䁧,䅺,䖢|shuo:嗍,妁,搠,朔,槊,欶,烁,爍,獡,矟,硕,碩,箾,蒴,说,鎙,鑠,铄,䀥,䈾,䌃|dia:嗲|cao:嘈,嶆,愺,懆,撡,操,曹,曺,槽,漕,糙,肏,艚,艸,艹,草,蓸,螬,褿,襙,鄵,鏪,騲,鼜,㜖,㯥,䄚,䏆,䐬,䒃,䒑|de:嘚,得,徳,德,恴,悳,惪,淂,的,鍀,锝,㝵,㤫,㥀,㥁,㯖,䙷,䙸|hei:嘿,嬒,潶,黑,黒|kuo:噋,廓,懖,扩,拡,括,挄,擴,栝,桰,濶,穒,筈,萿,葀,蛞,闊,阔,霩,鞟,鞹,韕,頢,髺,鬠,㗥,䟯,䦢,䯺|ca:嚓,囃,擦,攃,礤,礸,遪,䟃,䵽|chuo:嚽,娕,娖,惙,戳,擉,歠,涰,磭,綽,绰,腏,趠,踔,輟,辍,辵,辶,逴,酫,鑡,齪,齱,龊,㚟,㲋,䂐,䃗,䄪,䆯,䇍,䋘,䍳,䓎,䮕|zen:囎,怎,譖,譛,谮,䫈|nin:囜,您,拰,脌,㤛,䋻,䚾,䛘|kun:困,坤,堃,堒,壸,壼,婫,尡,崐,崑,悃,捆,昆,晜,梱,涃,潉,焜,熴,猑,琨,瑻,睏,硱,祵,稇,稛,綑,臗,菎,蜫,裈,裍,裩,褌,醌,錕,锟,閫,閸,阃,騉,髠,髡,髨,鯤,鲲,鵾,鶤,鹍,㩲,㫻,䠅|qun:囷,夋,宭,峮,帬,羣,群,裙,裠,輑,逡,㪊,㿏,䭽|ri:囸,日,釰,鈤,馹,驲,䒤|lve:圙,擽,畧,稤,稥,鋝,鋢,锊,㑼,㔀,㨼,䂮,䌎,䛚,䤣|zhui:坠,墜,娷,惴,椎,沝,甀,畷,硾,礈,笍,綴,縋,缀,缒,膇,諈,贅,赘,轛,追,醊,錐,錣,鑆,锥,隹,餟,騅,骓,鵻,䄌|hang:垳,夯,妔,斻,杭,沆,笐,筕,絎,绗,航,苀,蚢,貥,迒,頏,颃,魧,㤚,䀪,䘕,䟘,䣈,䦳,䲳,䴂|sao:埽,嫂,慅,扫,掃,掻,搔,氉,溞,瘙,矂,繅,缫,臊,颾,騒,騷,骚,髞,鰠,鱢,鳋,㛮,㿋,䐹,䕅,䖣|zang:塟,奘,弉,牂,羘,脏,臓,臟,臧,葬,賍,賘,贓,贜,赃,銺,駔,驵,髒,㘸|zeng:増,增,憎,曽,曾,橧,熷,璔,甑,矰,磳,繒,缯,罾,譄,贈,赠,鄫,鋥,锃,鱛,㽪,䙢,䰝|en:奀,峎,恩,摁,煾,蒽,䅰,䊐,䬶,䭓,䭡|zou:奏,媰,掫,揍,棷,棸,箃,緅,菆,諏,诹,走,赱,邹,郰,鄒,鄹,陬,騶,驺,鯐,鯫,鲰,黀,齺,㔿,㵵,䠫|nv:女,恧,朒,籹,衂,衄,釹,钕,㵖,䖡,䘐,䚼,䶊|nuan:奻,暖,渜,煖,煗,餪,㬉,䎡,䙇|niu:妞,忸,扭,杻,汼,沑,炄,牛,牜,狃,紐,纽,莥,鈕,钮,靵,㺲,䀔,䋴,䏔,䒜|rao:娆,嬈,扰,擾,桡,橈,犪,繞,绕,荛,蕘,襓,遶,隢,饒,饶,㑱,㹛,䫞|niang:娘,嬢,孃,酿,醸,釀,䖆|niao:嫋,嬝,嬲,尿,脲,茑,茒,蔦,袅,裊,褭,鳥,鸟,㒟,㜵,㞙,㠡,㭤,㳮,䃵,䐁,䙚,䦊,䮍|nen:嫩,㜛,㯎,㶧|sun:孙,孫,巺,损,損,搎,榫,槂,潠,狲,猻,畃,笋,筍,箰,簨,荪,蓀,蕵,薞,鎨,隼,飧,飱,鶽,㔼,㡄,㦏,䁚|kuan:宽,寛,寬,梡,欵,款,歀,窽,窾,鑧,髋,髖,㯘,䕀,䤭,䥗,䲌|yen:岃,膶|ang:岇,昂,昻,枊,盎,肮,醠,骯,㦹,㭿,㼜,䀚,䍩,䒢,䩕,䭹,䭺|cen:岑,嵾,梣,涔,笒,膥,㞥,㻸,䃡,䅾,䤁,䨙,䯔,䲋|cuan:巑,撺,攅,攛,櫕,欑,殩,汆,熶,爨,穳,窜,竄,篡,篹,簒,蹿,躥,鑹,㠝,㭫,㵀,㸑,䆘,䰖|te:忑,忒,慝,特,犆,脦,蟘,貣,鋱,铽,㥂,㧹|re:惹,热,熱|den:扥,扽,揼|zhua:抓,檛,爪,簻,膼,髽|shuan:拴,栓,涮,腨,閂,闩,䧠|zhuai:拽,跩|lue:掠,略|shai:晒,曬,筛,篩,簁,簛,㩄,㬠|sen:森|run:橍,润,潤,閏,閠,闰,㠈,䦞|nue:疟,虐|nve:瘧,䖈,䖋,䨋|gei:給,给|miu:繆,缪,謬,谬|neng:能,㲌,㴰,䏻|zei:蠈,賊,贼,鰂,鱡,鲗|fiao:覅|eng:鞥|ng:㕶|chua:䫄';
$rows = explode('|', $data);
$map = array();
foreach($rows as $v) {
list($py, $vals) = explode(':', $v);
$chars = explode(',', $vals);
foreach ($chars as $char) {
$map[$char] = $py;
}
}
return $map;
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/QRcode.class.php'
<?php
/*
* PHP QR Code encoder
*
* This file contains MERGED version of PHP QR Code library.
* It was auto-generated from full version for your convenience.
*
* This merged version was configured to not requre any external files,
* with disabled cache, error loging and weker but faster mask matching.
* If you need tune it up please use non-merged version.
*
* For full version, documentation, examples of use please visit:
*
* http://phpqrcode.sourceforge.net/
* https://sourceforge.net/projects/phpqrcode/
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Version: 1.1.4
* Build: 2010100721
*/
//---- qrconst.php -----------------------------
/*
* PHP QR Code encoder
*
* Common constants
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Encoding modes
define('QR_MODE_NUL', -1);
define('QR_MODE_NUM', 0);
define('QR_MODE_AN', 1);
define('QR_MODE_8', 2);
define('QR_MODE_KANJI', 3);
define('QR_MODE_STRUCTURE', 4);
// Levels of error correction.
define('QR_ECLEVEL_L', 0);
define('QR_ECLEVEL_M', 1);
define('QR_ECLEVEL_Q', 2);
define('QR_ECLEVEL_H', 3);
// Supported output formats
define('QR_FORMAT_TEXT', 0);
define('QR_FORMAT_PNG', 1);
class qrstr {
public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
$srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
}
}
//---- merged_config.php -----------------------------
/*
* PHP QR Code encoder
*
* Config file, tuned-up for merged verion
*/
define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there
define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true
define('QR_LOG_DIR', false); // default error logs dir
define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
//---- qrtools.php -----------------------------
/*
* PHP QR Code encoder
*
* Toolset, handy and debug utilites.
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class QRtools {
//----------------------------------------------------------------------
public static function binarize($frame)
{
$len = count($frame);
foreach ($frame as &$frameLine) {
for($i=0; $i<$len; $i++) {
$frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
}
}
return $frame;
}
//----------------------------------------------------------------------
public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
{
$barcode_array = array();
if (!is_array($mode))
$mode = explode(',', $mode);
$eccLevel = 'L';
if (count($mode) > 1) {
$eccLevel = $mode[1];
}
$qrTab = QRcode::text($code, false, $eccLevel);
$size = count($qrTab);
$barcode_array['num_rows'] = $size;
$barcode_array['num_cols'] = $size;
$barcode_array['bcode'] = array();
foreach ($qrTab as $line) {
$arrAdd = array();
foreach(str_split($line) as $char)
$arrAdd[] = ($char=='1')?1:0;
$barcode_array['bcode'][] = $arrAdd;
}
return $barcode_array;
}
//----------------------------------------------------------------------
public static function clearCache()
{
self::$frames = array();
}
//----------------------------------------------------------------------
public static function buildCache()
{
QRtools::markTime('before_build_cache');
$mask = new QRmask();
for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
$frame = QRspec::newFrame($a);
if (QR_IMAGE) {
$fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
QRimage::png(self::binarize($frame), $fileName, 1, 0);
}
$width = count($frame);
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
for ($maskNo=0; $maskNo<8; $maskNo++)
$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
}
QRtools::markTime('after_build_cache');
}
//----------------------------------------------------------------------
public static function log($outfile, $err)
{
if (QR_LOG_DIR !== false) {
if ($err != '') {
if ($outfile !== false) {
file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
} else {
file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
}
}
}
}
//----------------------------------------------------------------------
public static function dumpMask($frame)
{
$width = count($frame);
for($y=0;$y<$width;$y++) {
for($x=0;$x<$width;$x++) {
echo ord($frame[$y][$x]).',';
}
}
}
//----------------------------------------------------------------------
public static function markTime($markerId)
{
list($usec, $sec) = explode(" ", microtime());
$time = ((float)$usec + (float)$sec);
if (!isset($GLOBALS['qr_time_bench']))
$GLOBALS['qr_time_bench'] = array();
$GLOBALS['qr_time_bench'][$markerId] = $time;
}
//----------------------------------------------------------------------
public static function timeBenchmark()
{
self::markTime('finish');
$lastTime = 0;
$startTime = 0;
$p = 0;
echo '<table cellpadding="3" cellspacing="1">
<thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
<tbody>';
foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
if ($p > 0) {
echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
} else {
$startTime = $thisTime;
}
$p++;
$lastTime = $thisTime;
}
echo '</tbody><tfoot>
<tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
</tfoot>
</table>';
}
}
//##########################################################################
QRtools::markTime('start');
//---- qrspec.php -----------------------------
/*
* PHP QR Code encoder
*
* QR Code specifications
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('QRSPEC_VERSION_MAX', 40);
define('QRSPEC_WIDTH_MAX', 177);
define('QRCAP_WIDTH', 0);
define('QRCAP_WORDS', 1);
define('QRCAP_REMINDER', 2);
define('QRCAP_EC', 3);
class QRspec {
public static $capacity = array(
array( 0, 0, 0, array( 0, 0, 0, 0)),
array( 21, 26, 0, array( 7, 10, 13, 17)), // 1
array( 25, 44, 7, array( 10, 16, 22, 28)),
array( 29, 70, 7, array( 15, 26, 36, 44)),
array( 33, 100, 7, array( 20, 36, 52, 64)),
array( 37, 134, 7, array( 26, 48, 72, 88)), // 5
array( 41, 172, 7, array( 36, 64, 96, 112)),
array( 45, 196, 0, array( 40, 72, 108, 130)),
array( 49, 242, 0, array( 48, 88, 132, 156)),
array( 53, 292, 0, array( 60, 110, 160, 192)),
array( 57, 346, 0, array( 72, 130, 192, 224)), //10
array( 61, 404, 0, array( 80, 150, 224, 264)),
array( 65, 466, 0, array( 96, 176, 260, 308)),
array( 69, 532, 0, array( 104, 198, 288, 352)),
array( 73, 581, 3, array( 120, 216, 320, 384)),
array( 77, 655, 3, array( 132, 240, 360, 432)), //15
array( 81, 733, 3, array( 144, 280, 408, 480)),
array( 85, 815, 3, array( 168, 308, 448, 532)),
array( 89, 901, 3, array( 180, 338, 504, 588)),
array( 93, 991, 3, array( 196, 364, 546, 650)),
array( 97, 1085, 3, array( 224, 416, 600, 700)), //20
array(101, 1156, 4, array( 224, 442, 644, 750)),
array(105, 1258, 4, array( 252, 476, 690, 816)),
array(109, 1364, 4, array( 270, 504, 750, 900)),
array(113, 1474, 4, array( 300, 560, 810, 960)),
array(117, 1588, 4, array( 312, 588, 870, 1050)), //25
array(121, 1706, 4, array( 336, 644, 952, 1110)),
array(125, 1828, 4, array( 360, 700, 1020, 1200)),
array(129, 1921, 3, array( 390, 728, 1050, 1260)),
array(133, 2051, 3, array( 420, 784, 1140, 1350)),
array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30
array(141, 2323, 3, array( 480, 868, 1290, 1530)),
array(145, 2465, 3, array( 510, 924, 1350, 1620)),
array(149, 2611, 3, array( 540, 980, 1440, 1710)),
array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
);
//----------------------------------------------------------------------
public static function getDataLength($version, $level)
{
return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
}
//----------------------------------------------------------------------
public static function getECCLength($version, $level)
{
return self::$capacity[$version][QRCAP_EC][$level];
}
//----------------------------------------------------------------------
public static function getWidth($version)
{
return self::$capacity[$version][QRCAP_WIDTH];
}
//----------------------------------------------------------------------
public static function getRemainder($version)
{
return self::$capacity[$version][QRCAP_REMINDER];
}
//----------------------------------------------------------------------
public static function getMinimumVersion($size, $level)
{
for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
$words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
if($words >= $size)
return $i;
}
return -1;
}
//######################################################################
public static $lengthTableBits = array(
array(10, 12, 14),
array( 9, 11, 13),
array( 8, 16, 16),
array( 8, 10, 12)
);
//----------------------------------------------------------------------
public static function lengthIndicator($mode, $version)
{
if ($mode == QR_MODE_STRUCTURE)
return 0;
if ($version <= 9) {
$l = 0;
} else if ($version <= 26) {
$l = 1;
} else {
$l = 2;
}
return self::$lengthTableBits[$mode][$l];
}
//----------------------------------------------------------------------
public static function maximumWords($mode, $version)
{
if($mode == QR_MODE_STRUCTURE)
return 3;
if($version <= 9) {
$l = 0;
} else if($version <= 26) {
$l = 1;
} else {
$l = 2;
}
$bits = self::$lengthTableBits[$mode][$l];
$words = (1 << $bits) - 1;
if($mode == QR_MODE_KANJI) {
$words *= 2; // the number of bytes is required
}
return $words;
}
// Error correction code -----------------------------------------------
// Table of the error correction code (Reed-Solomon block)
// See Table 12-16 (pp.30-36), JIS X0510:2004.
public static $eccTable = array(
array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5
array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)),
array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)),
array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)),
array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10
array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)),
array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)),
array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15
array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)),
array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)),
array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20
array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)),
array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25
array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)),
array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35
array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40
);
//----------------------------------------------------------------------
// CACHEABLE!!!
public static function getEccSpec($version, $level, array &$spec)
{
if (count($spec) < 5) {
$spec = array(0,0,0,0,0);
}
$b1 = self::$eccTable[$version][$level][0];
$b2 = self::$eccTable[$version][$level][1];
$data = self::getDataLength($version, $level);
$ecc = self::getECCLength($version, $level);
if($b2 == 0) {
$spec[0] = $b1;
$spec[1] = (int)($data / $b1);
$spec[2] = (int)($ecc / $b1);
$spec[3] = 0;
$spec[4] = 0;
} else {
$spec[0] = $b1;
$spec[1] = (int)($data / ($b1 + $b2));
$spec[2] = (int)($ecc / ($b1 + $b2));
$spec[3] = $b2;
$spec[4] = $spec[1] + 1;
}
}
// Alignment pattern ---------------------------------------------------
// Positions of alignment patterns.
// This array includes only the second and the third position of the
// alignment patterns. Rest of them can be calculated from the distance
// between them.
// See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
public static $alignmentPattern = array(
array( 0, 0),
array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5
array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
);
/** --------------------------------------------------------------------
* Put an alignment marker.
* @param frame
* @param width
* @param ox,oy center coordinate of the pattern
*/
public static function putAlignmentMarker(array &$frame, $ox, $oy)
{
$finder = array(
"\xa1\xa1\xa1\xa1\xa1",
"\xa1\xa0\xa0\xa0\xa1",
"\xa1\xa0\xa1\xa0\xa1",
"\xa1\xa0\xa0\xa0\xa1",
"\xa1\xa1\xa1\xa1\xa1"
);
$yStart = $oy-2;
$xStart = $ox-2;
for($y=0; $y<5; $y++) {
QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]);
}
}
//----------------------------------------------------------------------
public static function putAlignmentPattern($version, &$frame, $width)
{
if($version < 2)
return;
$d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
if($d < 0) {
$w = 2;
} else {
$w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
}
if($w * $w - 3 == 1) {
$x = self::$alignmentPattern[$version][0];
$y = self::$alignmentPattern[$version][0];
self::putAlignmentMarker($frame, $x, $y);
return;
}
$cx = self::$alignmentPattern[$version][0];
for($x=1; $x<$w - 1; $x++) {
self::putAlignmentMarker($frame, 6, $cx);
self::putAlignmentMarker($frame, $cx, 6);
$cx += $d;
}
$cy = self::$alignmentPattern[$version][0];
for($y=0; $y<$w-1; $y++) {
$cx = self::$alignmentPattern[$version][0];
for($x=0; $x<$w-1; $x++) {
self::putAlignmentMarker($frame, $cx, $cy);
$cx += $d;
}
$cy += $d;
}
}
// Version information pattern -----------------------------------------
// Version information pattern (BCH coded).
// See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
// size: [QRSPEC_VERSION_MAX - 6]
public static $versionPattern = array(
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
);
//----------------------------------------------------------------------
public static function getVersionPattern($version)
{
if($version < 7 || $version > QRSPEC_VERSION_MAX)
return 0;
return self::$versionPattern[$version -7];
}
// Format information --------------------------------------------------
// See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
public static $formatInfo = array(
array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
);
public static function getFormatInfo($mask, $level)
{
if($mask < 0 || $mask > 7)
return 0;
if($level < 0 || $level > 3)
return 0;
return self::$formatInfo[$level][$mask];
}
// Frame ---------------------------------------------------------------
// Cache of initial frames.
public static $frames = array();
/** --------------------------------------------------------------------
* Put a finder pattern.
* @param frame
* @param width
* @param ox,oy upper-left coordinate of the pattern
*/
public static function putFinderPattern(&$frame, $ox, $oy)
{
$finder = array(
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
"\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
"\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
);
for($y=0; $y<7; $y++) {
QRstr::set($frame, $ox, $oy+$y, $finder[$y]);
}
}
//----------------------------------------------------------------------
public static function createFrame($version)
{
$width = self::$capacity[$version][QRCAP_WIDTH];
$frameLine = str_repeat ("\0", $width);
$frame = array_fill(0, $width, $frameLine);
// Finder pattern
self::putFinderPattern($frame, 0, 0);
self::putFinderPattern($frame, $width - 7, 0);
self::putFinderPattern($frame, 0, $width - 7);
// Separator
$yOffset = $width - 7;
for($y=0; $y<7; $y++) {
$frame[$y][7] = "\xc0";
$frame[$y][$width - 8] = "\xc0";
$frame[$yOffset][7] = "\xc0";
$yOffset++;
}
$setPattern = str_repeat("\xc0", 8);
QRstr::set($frame, 0, 7, $setPattern);
QRstr::set($frame, $width-8, 7, $setPattern);
QRstr::set($frame, 0, $width - 8, $setPattern);
// Format info
$setPattern = str_repeat("\x84", 9);
QRstr::set($frame, 0, 8, $setPattern);
QRstr::set($frame, $width - 8, 8, $setPattern, 8);
$yOffset = $width - 8;
for($y=0; $y<8; $y++,$yOffset++) {
$frame[$y][8] = "\x84";
$frame[$yOffset][8] = "\x84";
}
// Timing pattern
for($i=1; $i<$width-15; $i++) {
$frame[6][7+$i] = chr(0x90 | ($i & 1));
$frame[7+$i][6] = chr(0x90 | ($i & 1));
}
// Alignment pattern
self::putAlignmentPattern($version, $frame, $width);
// Version information
if($version >= 7) {
$vinf = self::getVersionPattern($version);
$v = $vinf;
for($x=0; $x<6; $x++) {
for($y=0; $y<3; $y++) {
$frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
$v = $v >> 1;
}
}
$v = $vinf;
for($y=0; $y<6; $y++) {
for($x=0; $x<3; $x++) {
$frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
$v = $v >> 1;
}
}
}
// and a little bit...
$frame[$width - 8][8] = "\x81";
return $frame;
}
//----------------------------------------------------------------------
public static function debug($frame, $binary_mode = false)
{
if ($binary_mode) {
foreach ($frame as &$frameLine) {
$frameLine = join('<span class="m"> </span>', explode('0', $frameLine));
$frameLine = join('██', explode('1', $frameLine));
}
?>
<style>
.m { background-color: white; }
</style>
<?php
echo '<pre><tt><br/ ><br/ ><br/ > ';
echo join("<br/ > ", $frame);
echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
} else {
foreach ($frame as &$frameLine) {
$frameLine = join('<span class="m"> </span>', explode("\xc0", $frameLine));
$frameLine = join('<span class="m">▒</span>', explode("\xc1", $frameLine));
$frameLine = join('<span class="p"> </span>', explode("\xa0", $frameLine));
$frameLine = join('<span class="p">▒</span>', explode("\xa1", $frameLine));
$frameLine = join('<span class="s">◇</span>', explode("\x84", $frameLine)); //format 0
$frameLine = join('<span class="s">◆</span>', explode("\x85", $frameLine)); //format 1
$frameLine = join('<span class="x">☢</span>', explode("\x81", $frameLine)); //special bit
$frameLine = join('<span class="c"> </span>', explode("\x90", $frameLine)); //clock 0
$frameLine = join('<span class="c">◷</span>', explode("\x91", $frameLine)); //clock 1
$frameLine = join('<span class="f"> </span>', explode("\x88", $frameLine)); //version
$frameLine = join('<span class="f">▒</span>', explode("\x89", $frameLine)); //version
$frameLine = join('♦', explode("\x01", $frameLine));
$frameLine = join('⋅', explode("\0", $frameLine));
}
?>
<style>
.p { background-color: yellow; }
.m { background-color: #00FF00; }
.s { background-color: #FF0000; }
.c { background-color: aqua; }
.x { background-color: pink; }
.f { background-color: gold; }
</style>
<?php
echo "<pre><tt>";
echo join("<br/ >", $frame);
echo "</tt></pre>";
}
}
//----------------------------------------------------------------------
public static function serial($frame)
{
return gzcompress(join("\n", $frame), 9);
}
//----------------------------------------------------------------------
public static function unserial($code)
{
return explode("\n", gzuncompress($code));
}
//----------------------------------------------------------------------
public static function newFrame($version)
{
if($version < 1 || $version > QRSPEC_VERSION_MAX)
return null;
if(!isset(self::$frames[$version])) {
$fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
if (QR_CACHEABLE) {
if (file_exists($fileName)) {
self::$frames[$version] = self::unserial(file_get_contents($fileName));
} else {
self::$frames[$version] = self::createFrame($version);
file_put_contents($fileName, self::serial(self::$frames[$version]));
}
} else {
self::$frames[$version] = self::createFrame($version);
}
}
if(is_null(self::$frames[$version]))
return null;
return self::$frames[$version];
}
//----------------------------------------------------------------------
public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; }
public static function rsBlockNum1($spec) { return $spec[0]; }
public static function rsDataCodes1($spec) { return $spec[1]; }
public static function rsEccCodes1($spec) { return $spec[2]; }
public static function rsBlockNum2($spec) { return $spec[3]; }
public static function rsDataCodes2($spec) { return $spec[4]; }
public static function rsEccCodes2($spec) { return $spec[2]; }
public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); }
public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; }
}
//---- qrimage.php -----------------------------
/*
* PHP QR Code encoder
*
* Image output of code using GD2
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('QR_IMAGE', true);
class QRimage {
//----------------------------------------------------------------------
public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
{
$image = self::image($frame, $pixelPerPoint, $outerFrame);
if ($filename === false) {
Header("Content-type: image/png");
ImagePng($image);
} else {
if($saveandprint===TRUE){
ImagePng($image, $filename);
header("Content-type: image/png");
ImagePng($image);
}else{
ImagePng($image, $filename);
}
}
ImageDestroy($image);
}
//----------------------------------------------------------------------
public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
{
$image = self::image($frame, $pixelPerPoint, $outerFrame);
if ($filename === false) {
Header("Content-type: image/jpeg");
ImageJpeg($image, null, $q);
} else {
ImageJpeg($image, $filename, $q);
}
ImageDestroy($image);
}
//----------------------------------------------------------------------
private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
{
$h = count($frame);
$w = strlen($frame[0]);
$imgW = $w + 2*$outerFrame;
$imgH = $h + 2*$outerFrame;
$base_image =ImageCreate($imgW, $imgH);
$col[0] = ImageColorAllocate($base_image,255,255,255);
$col[1] = ImageColorAllocate($base_image,0,0,0);
imagefill($base_image, 0, 0, $col[0]);
for($y=0; $y<$h; $y++) {
for($x=0; $x<$w; $x++) {
if ($frame[$y][$x] == '1') {
ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
}
}
}
$target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
ImageDestroy($base_image);
return $target_image;
}
}
//---- qrinput.php -----------------------------
/*
* PHP QR Code encoder
*
* Input encoding class
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('STRUCTURE_HEADER_BITS', 20);
define('MAX_STRUCTURED_SYMBOLS', 16);
class QRinputItem {
public $mode;
public $size;
public $data;
public $bstream;
public function __construct($mode, $size, $data, $bstream = null)
{
$setData = array_slice($data, 0, $size);
if (count($setData) < $size) {
$setData = array_merge($setData, array_fill(0,$size-count($setData),0));
}
if(!QRinput::check($mode, $size, $setData)) {
throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
return null;
}
$this->mode = $mode;
$this->size = $size;
$this->data = $setData;
$this->bstream = $bstream;
}
//----------------------------------------------------------------------
public function encodeModeNum($version)
{
try {
$words = (int)($this->size / 3);
$bs = new QRbitstream();
$val = 0x1;
$bs->appendNum(4, $val);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
for($i=0; $i<$words; $i++) {
$val = (ord($this->data[$i*3 ]) - ord('0')) * 100;
$val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
$val += (ord($this->data[$i*3+2]) - ord('0'));
$bs->appendNum(10, $val);
}
if($this->size - $words * 3 == 1) {
$val = ord($this->data[$words*3]) - ord('0');
$bs->appendNum(4, $val);
} else if($this->size - $words * 3 == 2) {
$val = (ord($this->data[$words*3 ]) - ord('0')) * 10;
$val += (ord($this->data[$words*3+1]) - ord('0'));
$bs->appendNum(7, $val);
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeModeAn($version)
{
try {
$words = (int)($this->size / 2);
$bs = new QRbitstream();
$bs->appendNum(4, 0x02);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
for($i=0; $i<$words; $i++) {
$val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45;
$val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
$bs->appendNum(11, $val);
}
if($this->size & 1) {
$val = QRinput::lookAnTable(ord($this->data[$words * 2]));
$bs->appendNum(6, $val);
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeMode8($version)
{
try {
$bs = new QRbitstream();
$bs->appendNum(4, 0x4);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
for($i=0; $i<$this->size; $i++) {
$bs->appendNum(8, ord($this->data[$i]));
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeModeKanji($version)
{
try {
$bs = new QRbitrtream();
$bs->appendNum(4, 0x8);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
for($i=0; $i<$this->size; $i+=2) {
$val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
if($val <= 0x9ffc) {
$val -= 0x8140;
} else {
$val -= 0xc140;
}
$h = ($val >> 8) * 0xc0;
$val = ($val & 0xff) + $h;
$bs->appendNum(13, $val);
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeModeStructure()
{
try {
$bs = new QRbitstream();
$bs->appendNum(4, 0x03);
$bs->appendNum(4, ord($this->data[1]) - 1);
$bs->appendNum(4, ord($this->data[0]) - 1);
$bs->appendNum(8, ord($this->data[2]));
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function estimateBitStreamSizeOfEntry($version)
{
$bits = 0;
if($version == 0)
$version = 1;
switch($this->mode) {
case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break;
case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break;
case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break;
case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break;
case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS;
default:
return 0;
}
$l = QRspec::lengthIndicator($this->mode, $version);
$m = 1 << $l;
$num = (int)(($this->size + $m - 1) / $m);
$bits += $num * (4 + $l);
return $bits;
}
//----------------------------------------------------------------------
public function encodeBitStream($version)
{
try {
unset($this->bstream);
$words = QRspec::maximumWords($this->mode, $version);
if($this->size > $words) {
$st1 = new QRinputItem($this->mode, $words, $this->data);
$st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
$st1->encodeBitStream($version);
$st2->encodeBitStream($version);
$this->bstream = new QRbitstream();
$this->bstream->append($st1->bstream);
$this->bstream->append($st2->bstream);
unset($st1);
unset($st2);
} else {
$ret = 0;
switch($this->mode) {
case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break;
case QR_MODE_AN: $ret = $this->encodeModeAn($version); break;
case QR_MODE_8: $ret = $this->encodeMode8($version); break;
case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break;
case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break;
default:
break;
}
if($ret < 0)
return -1;
}
return $this->bstream->size();
} catch (Exception $e) {
return -1;
}
}
};
//##########################################################################
class QRinput {
public $items;
private $version;
private $level;
//----------------------------------------------------------------------
public function __construct($version = 0, $level = QR_ECLEVEL_L)
{
if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
throw new Exception('Invalid version no');
return NULL;
}
$this->version = $version;
$this->level = $level;
}
//----------------------------------------------------------------------
public function getVersion()
{
return $this->version;
}
//----------------------------------------------------------------------
public function setVersion($version)
{
if($version < 0 || $version > QRSPEC_VERSION_MAX) {
throw new Exception('Invalid version no');
return -1;
}
$this->version = $version;
return 0;
}
//----------------------------------------------------------------------
public function getErrorCorrectionLevel()
{
return $this->level;
}
//----------------------------------------------------------------------
public function setErrorCorrectionLevel($level)
{
if($level > QR_ECLEVEL_H) {
throw new Exception('Invalid ECLEVEL');
return -1;
}
$this->level = $level;
return 0;
}
//----------------------------------------------------------------------
public function appendEntry(QRinputItem $entry)
{
$this->items[] = $entry;
}
//----------------------------------------------------------------------
public function append($mode, $size, $data)
{
try {
$entry = new QRinputItem($mode, $size, $data);
$this->items[] = $entry;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function insertStructuredAppendHeader($size, $index, $parity)
{
if( $size > MAX_STRUCTURED_SYMBOLS ) {
throw new Exception('insertStructuredAppendHeader wrong size');
}
if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
throw new Exception('insertStructuredAppendHeader wrong index');
}
$buf = array($size, $index, $parity);
try {
$entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
array_unshift($this->items, $entry);
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function calcParity()
{
$parity = 0;
foreach($this->items as $item) {
if($item->mode != QR_MODE_STRUCTURE) {
for($i=$item->size-1; $i>=0; $i--) {
$parity ^= $item->data[$i];
}
}
}
return $parity;
}
//----------------------------------------------------------------------
public static function checkModeNum($size, $data)
{
for($i=0; $i<$size; $i++) {
if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
return false;
}
}
return true;
}
//----------------------------------------------------------------------
public static function estimateBitsModeNum($size)
{
$w = (int)$size / 3;
$bits = $w * 10;
switch($size - $w * 3) {
case 1:
$bits += 4;
break;
case 2:
$bits += 7;
break;
default:
break;
}
return $bits;
}
//----------------------------------------------------------------------
public static $anTable = array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
);
//----------------------------------------------------------------------
public static function lookAnTable($c)
{
return (($c > 127)?-1:self::$anTable[$c]);
}
//----------------------------------------------------------------------
public static function checkModeAn($size, $data)
{
for($i=0; $i<$size; $i++) {
if (self::lookAnTable(ord($data[$i])) == -1) {
return false;
}
}
return true;
}
//----------------------------------------------------------------------
public static function estimateBitsModeAn($size)
{
$w = (int)($size / 2);
$bits = $w * 11;
if($size & 1) {
$bits += 6;
}
return $bits;
}
//----------------------------------------------------------------------
public static function estimateBitsMode8($size)
{
return $size * 8;
}
//----------------------------------------------------------------------
public function estimateBitsModeKanji($size)
{
return (int)(($size / 2) * 13);
}
//----------------------------------------------------------------------
public static function checkModeKanji($size, $data)
{
if($size & 1)
return false;
for($i=0; $i<$size; $i+=2) {
$val = (ord($data[$i]) << 8) | ord($data[$i+1]);
if( $val < 0x8140
|| ($val > 0x9ffc && $val < 0xe040)
|| $val > 0xebbf) {
return false;
}
}
return true;
}
/***********************************************************************
* Validation
**********************************************************************/
public static function check($mode, $size, $data)
{
if($size <= 0)
return false;
switch($mode) {
case QR_MODE_NUM: return self::checkModeNum($size, $data); break;
case QR_MODE_AN: return self::checkModeAn($size, $data); break;
case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break;
case QR_MODE_8: return true; break;
case QR_MODE_STRUCTURE: return true; break;
default:
break;
}
return false;
}
//----------------------------------------------------------------------
public function estimateBitStreamSize($version)
{
$bits = 0;
foreach($this->items as $item) {
$bits += $item->estimateBitStreamSizeOfEntry($version);
}
return $bits;
}
//----------------------------------------------------------------------
public function estimateVersion()
{
$version = 0;
$prev = 0;
do {
$prev = $version;
$bits = $this->estimateBitStreamSize($prev);
$version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
if ($version < 0) {
return -1;
}
} while ($version > $prev);
return $version;
}
//----------------------------------------------------------------------
public static function lengthOfCode($mode, $version, $bits)
{
$payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
switch($mode) {
case QR_MODE_NUM:
$chunks = (int)($payload / 10);
$remain = $payload - $chunks * 10;
$size = $chunks * 3;
if($remain >= 7) {
$size += 2;
} else if($remain >= 4) {
$size += 1;
}
break;
case QR_MODE_AN:
$chunks = (int)($payload / 11);
$remain = $payload - $chunks * 11;
$size = $chunks * 2;
if($remain >= 6)
$size++;
break;
case QR_MODE_8:
$size = (int)($payload / 8);
break;
case QR_MODE_KANJI:
$size = (int)(($payload / 13) * 2);
break;
case QR_MODE_STRUCTURE:
$size = (int)($payload / 8);
break;
default:
$size = 0;
break;
}
$maxsize = QRspec::maximumWords($mode, $version);
if($size < 0) $size = 0;
if($size > $maxsize) $size = $maxsize;
return $size;
}
//----------------------------------------------------------------------
public function createBitStream()
{
$total = 0;
foreach($this->items as $item) {
$bits = $item->encodeBitStream($this->version);
if($bits < 0)
return -1;
$total += $bits;
}
return $total;
}
//----------------------------------------------------------------------
public function convertData()
{
$ver = $this->estimateVersion();
if($ver > $this->getVersion()) {
$this->setVersion($ver);
}
for(;;) {
$bits = $this->createBitStream();
if($bits < 0)
return -1;
$ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
if($ver < 0) {
throw new Exception('WRONG VERSION');
return -1;
} else if($ver > $this->getVersion()) {
$this->setVersion($ver);
} else {
break;
}
}
return 0;
}
//----------------------------------------------------------------------
public function appendPaddingBit(&$bstream)
{
$bits = $bstream->size();
$maxwords = QRspec::getDataLength($this->version, $this->level);
$maxbits = $maxwords * 8;
if ($maxbits == $bits) {
return 0;
}
if ($maxbits - $bits < 5) {
return $bstream->appendNum($maxbits - $bits, 0);
}
$bits += 4;
$words = (int)(($bits + 7) / 8);
$padding = new QRbitstream();
$ret = $padding->appendNum($words * 8 - $bits + 4, 0);
if($ret < 0)
return $ret;
$padlen = $maxwords - $words;
if($padlen > 0) {
$padbuf = array();
for($i=0; $i<$padlen; $i++) {
$padbuf[$i] = ($i&1)?0x11:0xec;
}
$ret = $padding->appendBytes($padlen, $padbuf);
if($ret < 0)
return $ret;
}
$ret = $bstream->append($padding);
return $ret;
}
//----------------------------------------------------------------------
public function mergeBitStream()
{
if($this->convertData() < 0) {
return null;
}
$bstream = new QRbitstream();
foreach($this->items as $item) {
$ret = $bstream->append($item->bstream);
if($ret < 0) {
return null;
}
}
return $bstream;
}
//----------------------------------------------------------------------
public function getBitStream()
{
$bstream = $this->mergeBitStream();
if($bstream == null) {
return null;
}
$ret = $this->appendPaddingBit($bstream);
if($ret < 0) {
return null;
}
return $bstream;
}
//----------------------------------------------------------------------
public function getByteStream()
{
$bstream = $this->getBitStream();
if($bstream == null) {
return null;
}
return $bstream->toByte();
}
}
//---- qrbitstream.php -----------------------------
/*
* PHP QR Code encoder
*
* Bitstream class
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class QRbitstream {
public $data = array();
//----------------------------------------------------------------------
public function size()
{
return count($this->data);
}
//----------------------------------------------------------------------
public function allocate($setLength)
{
$this->data = array_fill(0, $setLength, 0);
return 0;
}
//----------------------------------------------------------------------
public static function newFromNum($bits, $num)
{
$bstream = new QRbitstream();
$bstream->allocate($bits);
$mask = 1 << ($bits - 1);
for($i=0; $i<$bits; $i++) {
if($num & $mask) {
$bstream->data[$i] = 1;
} else {
$bstream->data[$i] = 0;
}
$mask = $mask >> 1;
}
return $bstream;
}
//----------------------------------------------------------------------
public static function newFromBytes($size, $data)
{
$bstream = new QRbitstream();
$bstream->allocate($size * 8);
$p=0;
for($i=0; $i<$size; $i++) {
$mask = 0x80;
for($j=0; $j<8; $j++) {
if($data[$i] & $mask) {
$bstream->data[$p] = 1;
} else {
$bstream->data[$p] = 0;
}
$p++;
$mask = $mask >> 1;
}
}
return $bstream;
}
//----------------------------------------------------------------------
public function append(QRbitstream $arg)
{
if (is_null($arg)) {
return -1;
}
if($arg->size() == 0) {
return 0;
}
if($this->size() == 0) {
$this->data = $arg->data;
return 0;
}
$this->data = array_values(array_merge($this->data, $arg->data));
return 0;
}
//----------------------------------------------------------------------
public function appendNum($bits, $num)
{
if ($bits == 0)
return 0;
$b = QRbitstream::newFromNum($bits, $num);
if(is_null($b))
return -1;
$ret = $this->append($b);
unset($b);
return $ret;
}
//----------------------------------------------------------------------
public function appendBytes($size, $data)
{
if ($size == 0)
return 0;
$b = QRbitstream::newFromBytes($size, $data);
if(is_null($b))
return -1;
$ret = $this->append($b);
unset($b);
return $ret;
}
//----------------------------------------------------------------------
public function toByte()
{
$size = $this->size();
if($size == 0) {
return array();
}
$data = array_fill(0, (int)(($size + 7) / 8), 0);
$bytes = (int)($size / 8);
$p = 0;
for($i=0; $i<$bytes; $i++) {
$v = 0;
for($j=0; $j<8; $j++) {
$v = $v << 1;
$v |= $this->data[$p];
$p++;
}
$data[$i] = $v;
}
if($size & 7) {
$v = 0;
for($j=0; $j<($size & 7); $j++) {
$v = $v << 1;
$v |= $this->data[$p];
$p++;
}
$data[$bytes] = $v;
}
return $data;
}
}
//---- qrsplit.php -----------------------------
/*
* PHP QR Code encoder
*
* Input splitting classes
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class QRsplit {
public $dataStr = '';
public $input;
public $modeHint;
//----------------------------------------------------------------------
public function __construct($dataStr, $input, $modeHint)
{
$this->dataStr = $dataStr;
$this->input = $input;
$this->modeHint = $modeHint;
}
//----------------------------------------------------------------------
public static function isdigitat($str, $pos)
{
if ($pos >= strlen($str))
return false;
return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
}
//----------------------------------------------------------------------
public static function isalnumat($str, $pos)
{
if ($pos >= strlen($str))
return false;
return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
}
//----------------------------------------------------------------------
public function identifyMode($pos)
{
if ($pos >= strlen($this->dataStr))
return QR_MODE_NUL;
$c = $this->dataStr[$pos];
if(self::isdigitat($this->dataStr, $pos)) {
return QR_MODE_NUM;
} else if(self::isalnumat($this->dataStr, $pos)) {
return QR_MODE_AN;
} else if($this->modeHint == QR_MODE_KANJI) {
if ($pos+1 < strlen($this->dataStr))
{
$d = $this->dataStr[$pos+1];
$word = (ord($c) << 8) | ord($d);
if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
return QR_MODE_KANJI;
}
}
}
return QR_MODE_8;
}
//----------------------------------------------------------------------
public function eatNum()
{
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 0;
while(self::isdigitat($this->dataStr, $p)) {
$p++;
}
$run = $p;
$mode = $this->identifyMode($p);
if($mode == QR_MODE_8) {
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+ QRinput::estimateBitsMode8(1) // + 4 + l8
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
if($dif > 0) {
return $this->eat8();
}
}
if($mode == QR_MODE_AN) {
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+ QRinput::estimateBitsModeAn(1) // + 4 + la
- QRinput::estimateBitsModeAn($run + 1);// - 4 - la
if($dif > 0) {
return $this->eatAn();
}
}
$ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function eatAn()
{
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 0;
while(self::isalnumat($this->dataStr, $p)) {
if(self::isdigitat($this->dataStr, $p)) {
$q = $p;
while(self::isdigitat($this->dataStr, $q)) {
$q++;
}
$dif = QRinput::estimateBitsModeAn($p) // + 4 + la
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
- QRinput::estimateBitsModeAn($q); // - 4 - la
if($dif < 0) {
break;
} else {
$p = $q;
}
} else {
$p++;
}
}
$run = $p;
if(!self::isalnumat($this->dataStr, $p)) {
$dif = QRinput::estimateBitsModeAn($run) + 4 + $la
+ QRinput::estimateBitsMode8(1) // + 4 + l8
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
if($dif > 0) {
return $this->eat8();
}
}
$ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function eatKanji()
{
$p = 0;
while($this->identifyMode($p) == QR_MODE_KANJI) {
$p += 2;
}
$ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function eat8()
{
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 1;
$dataStrLen = strlen($this->dataStr);
while($p < $dataStrLen) {
$mode = $this->identifyMode($p);
if($mode == QR_MODE_KANJI) {
break;
}
if($mode == QR_MODE_NUM) {
$q = $p;
while(self::isdigitat($this->dataStr, $q)) {
$q++;
}
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
- QRinput::estimateBitsMode8($q); // - 4 - l8
if($dif < 0) {
break;
} else {
$p = $q;
}
} else if($mode == QR_MODE_AN) {
$q = $p;
while(self::isalnumat($this->dataStr, $q)) {
$q++;
}
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+ QRinput::estimateBitsModeAn($q - $p) + 4 + $la
- QRinput::estimateBitsMode8($q); // - 4 - l8
if($dif < 0) {
break;
} else {
$p = $q;
}
} else {
$p++;
}
}
$run = $p;
$ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function splitString()
{
while (strlen($this->dataStr) > 0)
{
if($this->dataStr == '')
return 0;
$mode = $this->identifyMode(0);
switch ($mode) {
case QR_MODE_NUM: $length = $this->eatNum(); break;
case QR_MODE_AN: $length = $this->eatAn(); break;
case QR_MODE_KANJI:
if ($hint == QR_MODE_KANJI)
$length = $this->eatKanji();
else $length = $this->eat8();
break;
default: $length = $this->eat8(); break;
}
if($length == 0) return 0;
if($length < 0) return -1;
$this->dataStr = substr($this->dataStr, $length);
}
}
//----------------------------------------------------------------------
public function toUpper()
{
$stringLen = strlen($this->dataStr);
$p = 0;
while ($p<$stringLen) {
$mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
if($mode == QR_MODE_KANJI) {
$p += 2;
} else {
if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
$this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
}
$p++;
}
}
return $this->dataStr;
}
//----------------------------------------------------------------------
public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
{
if(is_null($string) || $string == '\0' || $string == '') {
throw new Exception('empty string!!!');
}
$split = new QRsplit($string, $input, $modeHint);
if(!$casesensitive)
$split->toUpper();
return $split->splitString();
}
}
//---- qrrscode.php -----------------------------
/*
* PHP QR Code encoder
*
* Reed-Solomon error correction support
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* (libfec is released under the GNU Lesser General Public License.)
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class QRrsItem {
public $mm; // Bits per symbol
public $nn; // Symbols per block (= (1<<mm)-1)
public $alpha_to = array(); // log lookup table
public $index_of = array(); // Antilog lookup table
public $genpoly = array(); // Generator polynomial
public $nroots; // Number of generator roots = number of parity symbols
public $fcr; // First consecutive root, index form
public $prim; // Primitive element, index form
public $iprim; // prim-th root of 1, index form
public $pad; // Padding bytes in shortened block
public $gfpoly;
//----------------------------------------------------------------------
public function modnn($x)
{
while ($x >= $this->nn) {
$x -= $this->nn;
$x = ($x >> $this->mm) + ($x & $this->nn);
}
return $x;
}
//----------------------------------------------------------------------
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
{
// Common code for intializing a Reed-Solomon control block (char or int symbols)
// Copyright 2004 Phil Karn, KA9Q
// May be used under the terms of the GNU Lesser General Public License (LGPL)
$rs = null;
// Check parameter ranges
if($symsize < 0 || $symsize > 8) return $rs;
if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;
if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;
if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!
if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
$rs = new QRrsItem();
$rs->mm = $symsize;
$rs->nn = (1<<$symsize)-1;
$rs->pad = $pad;
$rs->alpha_to = array_fill(0, $rs->nn+1, 0);
$rs->index_of = array_fill(0, $rs->nn+1, 0);
// PHP style macro replacement ;)
$NN =& $rs->nn;
$A0 =& $NN;
// Generate Galois field lookup tables
$rs->index_of[0] = $A0; // log(zero) = -inf
$rs->alpha_to[$A0] = 0; // alpha**-inf = 0
$sr = 1;
for($i=0; $i<$rs->nn; $i++) {
$rs->index_of[$sr] = $i;
$rs->alpha_to[$i] = $sr;
$sr <<= 1;
if($sr & (1<<$symsize)) {
$sr ^= $gfpoly;
}
$sr &= $rs->nn;
}
if($sr != 1){
// field generator polynomial is not primitive!
$rs = NULL;
return $rs;
}
/* Form RS code generator polynomial from its roots */
$rs->genpoly = array_fill(0, $nroots+1, 0);
$rs->fcr = $fcr;
$rs->prim = $prim;
$rs->nroots = $nroots;
$rs->gfpoly = $gfpoly;
/* Find prim-th root of 1, used in decoding */
for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
; // intentional empty-body loop!
$rs->iprim = (int)($iprim / $prim);
$rs->genpoly[0] = 1;
for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
$rs->genpoly[$i+1] = 1;
// Multiply rs->genpoly[] by @**(root + x)
for ($j = $i; $j > 0; $j--) {
if ($rs->genpoly[$j] != 0) {
$rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
} else {
$rs->genpoly[$j] = $rs->genpoly[$j-1];
}
}
// rs->genpoly[0] can never be zero
$rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
}
// convert rs->genpoly[] to index form for quicker encoding
for ($i = 0; $i <= $nroots; $i++)
$rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
return $rs;
}
//----------------------------------------------------------------------
public function encode_rs_char($data, &$parity)
{
$MM =& $this->mm;
$NN =& $this->nn;
$ALPHA_TO =& $this->alpha_to;
$INDEX_OF =& $this->index_of;
$GENPOLY =& $this->genpoly;
$NROOTS =& $this->nroots;
$FCR =& $this->fcr;
$PRIM =& $this->prim;
$IPRIM =& $this->iprim;
$PAD =& $this->pad;
$A0 =& $NN;
$parity = array_fill(0, $NROOTS, 0);
for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
$feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
if($feedback != $A0) {
// feedback term is non-zero
// This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
// always be for the polynomials constructed by init_rs()
$feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
for($j=1;$j<$NROOTS;$j++) {
$parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
}
}
// Shift
array_shift($parity);
if($feedback != $A0) {
array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
} else {
array_push($parity, 0);
}
}
}
}
//##########################################################################
class QRrs {
public static $items = array();
//----------------------------------------------------------------------
public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
{
foreach(self::$items as $rs) {
if($rs->pad != $pad) continue;
if($rs->nroots != $nroots) continue;
if($rs->mm != $symsize) continue;
if($rs->gfpoly != $gfpoly) continue;
if($rs->fcr != $fcr) continue;
if($rs->prim != $prim) continue;
return $rs;
}
$rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
array_unshift(self::$items, $rs);
return $rs;
}
}
//---- qrmask.php -----------------------------
/*
* PHP QR Code encoder
*
* Masking
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('N1', 3);
define('N2', 3);
define('N3', 40);
define('N4', 10);
class QRmask {
public $runLength = array();
//----------------------------------------------------------------------
public function __construct()
{
$this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
}
//----------------------------------------------------------------------
public function writeFormatInformation($width, &$frame, $mask, $level)
{
$blacks = 0;
$format = QRspec::getFormatInfo($mask, $level);
for($i=0; $i<8; $i++) {
if($format & 1) {
$blacks += 2;
$v = 0x85;
} else {
$v = 0x84;
}
$frame[8][$width - 1 - $i] = chr($v);
if($i < 6) {
$frame[$i][8] = chr($v);
} else {
$frame[$i + 1][8] = chr($v);
}
$format = $format >> 1;
}
for($i=0; $i<7; $i++) {
if($format & 1) {
$blacks += 2;
$v = 0x85;
} else {
$v = 0x84;
}
$frame[$width - 7 + $i][8] = chr($v);
if($i == 0) {
$frame[8][7] = chr($v);
} else {
$frame[8][6 - $i] = chr($v);
}
$format = $format >> 1;
}
return $blacks;
}
//----------------------------------------------------------------------
public function mask0($x, $y) { return ($x+$y)&1; }
public function mask1($x, $y) { return ($y&1); }
public function mask2($x, $y) { return ($x%3); }
public function mask3($x, $y) { return ($x+$y)%3; }
public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
//----------------------------------------------------------------------
private function generateMaskNo($maskNo, $width, $frame)
{
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
for($y=0; $y<$width; $y++) {
for($x=0; $x<$width; $x++) {
if(ord($frame[$y][$x]) & 0x80) {
$bitMask[$y][$x] = 0;
} else {
$maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
$bitMask[$y][$x] = ($maskFunc == 0)?1:0;
}
}
}
return $bitMask;
}
//----------------------------------------------------------------------
public static function serial($bitFrame)
{
$codeArr = array();
foreach ($bitFrame as $line)
$codeArr[] = join('', $line);
return gzcompress(join("\n", $codeArr), 9);
}
//----------------------------------------------------------------------
public static function unserial($code)
{
$codeArr = array();
$codeLines = explode("\n", gzuncompress($code));
foreach ($codeLines as $line)
$codeArr[] = str_split($line);
return $codeArr;
}
//----------------------------------------------------------------------
public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
{
$b = 0;
$bitMask = array();
$fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
if (QR_CACHEABLE) {
if (file_exists($fileName)) {
$bitMask = self::unserial(file_get_contents($fileName));
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
file_put_contents($fileName, self::serial($bitMask));
}
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
}
if ($maskGenOnly)
return;
$d = $s;
for($y=0; $y<$width; $y++) {
for($x=0; $x<$width; $x++) {
if($bitMask[$y][$x] == 1) {
$d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
}
$b += (int)(ord($d[$y][$x]) & 1);
}
}
return $b;
}
//----------------------------------------------------------------------
public function makeMask($width, $frame, $maskNo, $level)
{
$masked = array_fill(0, $width, str_repeat("\0", $width));
$this->makeMaskNo($maskNo, $width, $frame, $masked);
$this->writeFormatInformation($width, $masked, $maskNo, $level);
return $masked;
}
//----------------------------------------------------------------------
public function calcN1N3($length)
{
$demerit = 0;
for($i=0; $i<$length; $i++) {
if($this->runLength[$i] >= 5) {
$demerit += (N1 + ($this->runLength[$i] - 5));
}
if($i & 1) {
if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
$fact = (int)($this->runLength[$i] / 3);
if(($this->runLength[$i-2] == $fact) &&
($this->runLength[$i-1] == $fact) &&
($this->runLength[$i+1] == $fact) &&
($this->runLength[$i+2] == $fact)) {
if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
$demerit += N3;
} else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
$demerit += N3;
}
}
}
}
}
return $demerit;
}
//----------------------------------------------------------------------
public function evaluateSymbol($width, $frame)
{
$head = 0;
$demerit = 0;
for($y=0; $y<$width; $y++) {
$head = 0;
$this->runLength[0] = 1;
$frameY = $frame[$y];
if ($y>0)
$frameYM = $frame[$y-1];
for($x=0; $x<$width; $x++) {
if(($x > 0) && ($y > 0)) {
$b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
$w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
if(($b22 | ($w22 ^ 1))&1) {
$demerit += N2;
}
}
if(($x == 0) && (ord($frameY[$x]) & 1)) {
$this->runLength[0] = -1;
$head = 1;
$this->runLength[$head] = 1;
} else if($x > 0) {
if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
$head++;
$this->runLength[$head] = 1;
} else {
$this->runLength[$head]++;
}
}
}
$demerit += $this->calcN1N3($head+1);
}
for($x=0; $x<$width; $x++) {
$head = 0;
$this->runLength[0] = 1;
for($y=0; $y<$width; $y++) {
if($y == 0 && (ord($frame[$y][$x]) & 1)) {
$this->runLength[0] = -1;
$head = 1;
$this->runLength[$head] = 1;
} else if($y > 0) {
if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
$head++;
$this->runLength[$head] = 1;
} else {
$this->runLength[$head]++;
}
}
}
$demerit += $this->calcN1N3($head+1);
}
return $demerit;
}
//----------------------------------------------------------------------
public function mask($width, $frame, $level)
{
$minDemerit = PHP_INT_MAX;
$bestMaskNum = 0;
$bestMask = array();
$checked_masks = array(0,1,2,3,4,5,6,7);
if (QR_FIND_FROM_RANDOM !== false) {
$howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
for ($i = 0; $i < $howManuOut; $i++) {
$remPos = rand (0, count($checked_masks)-1);
unset($checked_masks[$remPos]);
$checked_masks = array_values($checked_masks);
}
}
$bestMask = $frame;
foreach($checked_masks as $i) {
$mask = array_fill(0, $width, str_repeat("\0", $width));
$demerit = 0;
$blacks = 0;
$blacks = $this->makeMaskNo($i, $width, $frame, $mask);
$blacks += $this->writeFormatInformation($width, $mask, $i, $level);
$blacks = (int)(100 * $blacks / ($width * $width));
$demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
$demerit += $this->evaluateSymbol($width, $mask);
if($demerit < $minDemerit) {
$minDemerit = $demerit;
$bestMask = $mask;
$bestMaskNum = $i;
}
}
return $bestMask;
}
//----------------------------------------------------------------------
}
//---- qrencode.php -----------------------------
/*
* PHP QR Code encoder
*
* Main encoder classes.
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class QRrsblock {
public $dataLength;
public $data = array();
public $eccLength;
public $ecc = array();
public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
{
$rs->encode_rs_char($data, $ecc);
$this->dataLength = $dl;
$this->data = $data;
$this->eccLength = $el;
$this->ecc = $ecc;
}
};
//##########################################################################
class QRrawcode {
public $version;
public $datacode = array();
public $ecccode = array();
public $blocks;
public $rsblocks = array(); //of RSblock
public $count;
public $dataLength;
public $eccLength;
public $b1;
//----------------------------------------------------------------------
public function __construct(QRinput $input)
{
$spec = array(0,0,0,0,0);
$this->datacode = $input->getByteStream();
if(is_null($this->datacode)) {
throw new Exception('null imput string');
}
QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
$this->version = $input->getVersion();
$this->b1 = QRspec::rsBlockNum1($spec);
$this->dataLength = QRspec::rsDataLength($spec);
$this->eccLength = QRspec::rsEccLength($spec);
$this->ecccode = array_fill(0, $this->eccLength, 0);
$this->blocks = QRspec::rsBlockNum($spec);
$ret = $this->init($spec);
if($ret < 0) {
throw new Exception('block alloc error');
return null;
}
$this->count = 0;
}
//----------------------------------------------------------------------
public function init(array $spec)
{
$dl = QRspec::rsDataCodes1($spec);
$el = QRspec::rsEccCodes1($spec);
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
$blockNo = 0;
$dataPos = 0;
$eccPos = 0;
for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) {
$ecc = array_slice($this->ecccode,$eccPos);
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
$dataPos += $dl;
$eccPos += $el;
$blockNo++;
}
if(QRspec::rsBlockNum2($spec) == 0)
return 0;
$dl = QRspec::rsDataCodes2($spec);
$el = QRspec::rsEccCodes2($spec);
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
if($rs == NULL) return -1;
for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) {
$ecc = array_slice($this->ecccode,$eccPos);
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
$dataPos += $dl;
$eccPos += $el;
$blockNo++;
}
return 0;
}
//----------------------------------------------------------------------
public function getCode()
{
$ret;
if($this->count < $this->dataLength) {
$row = $this->count % $this->blocks;
$col = $this->count / $this->blocks;
if($col >= $this->rsblocks[0]->dataLength) {
$row += $this->b1;
}
$ret = $this->rsblocks[$row]->data[$col];
} else if($this->count < $this->dataLength + $this->eccLength) {
$row = ($this->count - $this->dataLength) % $this->blocks;
$col = ($this->count - $this->dataLength) / $this->blocks;
$ret = $this->rsblocks[$row]->ecc[$col];
} else {
return 0;
}
$this->count++;
return $ret;
}
}
//##########################################################################
class QRcode {
public $version;
public $width;
public $data;
//----------------------------------------------------------------------
public function encodeMask(QRinput $input, $mask)
{
if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
throw new Exception('wrong version');
}
if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
throw new Exception('wrong level');
}
$raw = new QRrawcode($input);
QRtools::markTime('after_raw');
$version = $raw->version;
$width = QRspec::getWidth($version);
$frame = QRspec::newFrame($version);
$filler = new FrameFiller($width, $frame);
if(is_null($filler)) {
return NULL;
}
// inteleaved data and ecc codes
for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
$code = $raw->getCode();
$bit = 0x80;
for($j=0; $j<8; $j++) {
$addr = $filler->next();
$filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
$bit = $bit >> 1;
}
}
QRtools::markTime('after_filler');
unset($raw);
// remainder bits
$j = QRspec::getRemainder($version);
for($i=0; $i<$j; $i++) {
$addr = $filler->next();
$filler->setFrameAt($addr, 0x02);
}
$frame = $filler->frame;
unset($filler);
// masking
$maskObj = new QRmask();
if($mask < 0) {
if (QR_FIND_BEST_MASK) {
$masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
} else {
$masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
}
} else {
$masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
}
if($masked == NULL) {
return NULL;
}
QRtools::markTime('after_mask');
$this->version = $version;
$this->width = $width;
$this->data = $masked;
return $this;
}
//----------------------------------------------------------------------
public function encodeInput(QRinput $input)
{
return $this->encodeMask($input, -1);
}
//----------------------------------------------------------------------
public function encodeString8bit($string, $version, $level)
{
if(string == NULL) {
throw new Exception('empty string!');
return NULL;
}
$input = new QRinput($version, $level);
if($input == NULL) return NULL;
$ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
if($ret < 0) {
unset($input);
return NULL;
}
return $this->encodeInput($input);
}
//----------------------------------------------------------------------
public function encodeString($string, $version, $level, $hint, $casesensitive)
{
if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
throw new Exception('bad hint');
return NULL;
}
$input = new QRinput($version, $level);
if($input == NULL) return NULL;
$ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
if($ret < 0) {
return NULL;
}
return $this->encodeInput($input);
}
//----------------------------------------------------------------------
public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
{
$enc = QRencode::factory($level, $size, $margin);
return $enc->encodePNG($text, $outfile, $saveandprint=false);
}
//----------------------------------------------------------------------
public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
{
$enc = QRencode::factory($level, $size, $margin);
return $enc->encode($text, $outfile);
}
//----------------------------------------------------------------------
public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
{
$enc = QRencode::factory($level, $size, $margin);
return $enc->encodeRAW($text, $outfile);
}
}
//##########################################################################
class FrameFiller {
public $width;
public $frame;
public $x;
public $y;
public $dir;
public $bit;
//----------------------------------------------------------------------
public function __construct($width, &$frame)
{
$this->width = $width;
$this->frame = $frame;
$this->x = $width - 1;
$this->y = $width - 1;
$this->dir = -1;
$this->bit = -1;
}
//----------------------------------------------------------------------
public function setFrameAt($at, $val)
{
$this->frame[$at['y']][$at['x']] = chr($val);
}
//----------------------------------------------------------------------
public function getFrameAt($at)
{
return ord($this->frame[$at['y']][$at['x']]);
}
//----------------------------------------------------------------------
public function next()
{
do {
if($this->bit == -1) {
$this->bit = 0;
return array('x'=>$this->x, 'y'=>$this->y);
}
$x = $this->x;
$y = $this->y;
$w = $this->width;
if($this->bit == 0) {
$x--;
$this->bit++;
} else {
$x++;
$y += $this->dir;
$this->bit--;
}
if($this->dir < 0) {
if($y < 0) {
$y = 0;
$x -= 2;
$this->dir = 1;
if($x == 6) {
$x--;
$y = 9;
}
}
} else {
if($y == $w) {
$y = $w - 1;
$x -= 2;
$this->dir = -1;
if($x == 6) {
$x--;
$y -= 8;
}
}
}
if($x < 0 || $y < 0) return null;
$this->x = $x;
$this->y = $y;
} while(ord($this->frame[$y][$x]) & 0x80);
return array('x'=>$x, 'y'=>$y);
}
} ;
//##########################################################################
class QRencode {
public $casesensitive = true;
public $eightbit = false;
public $version = 0;
public $size = 3;
public $margin = 4;
public $structured = 0; // not supported yet
public $level = QR_ECLEVEL_L;
public $hint = QR_MODE_8;
//----------------------------------------------------------------------
public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4)
{
$enc = new QRencode();
$enc->size = $size;
$enc->margin = $margin;
switch ($level.'') {
case '0':
case '1':
case '2':
case '3':
$enc->level = $level;
break;
case 'l':
case 'L':
$enc->level = QR_ECLEVEL_L;
break;
case 'm':
case 'M':
$enc->level = QR_ECLEVEL_M;
break;
case 'q':
case 'Q':
$enc->level = QR_ECLEVEL_Q;
break;
case 'h':
case 'H':
$enc->level = QR_ECLEVEL_H;
break;
}
return $enc;
}
//----------------------------------------------------------------------
public function encodeRAW($intext, $outfile = false)
{
$code = new QRcode();
if($this->eightbit) {
$code->encodeString8bit($intext, $this->version, $this->level);
} else {
$code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
}
return $code->data;
}
//----------------------------------------------------------------------
public function encode($intext, $outfile = false)
{
$code = new QRcode();
if($this->eightbit) {
$code->encodeString8bit($intext, $this->version, $this->level);
} else {
$code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
}
QRtools::markTime('after_encode');
if ($outfile!== false) {
file_put_contents($outfile, join("\n", QRtools::binarize($code->data)));
} else {
return QRtools::binarize($code->data);
}
}
//----------------------------------------------------------------------
public function encodePNG($intext, $outfile = false,$saveandprint=false)
{
try {
ob_start();
$tab = $this->encode($intext);
$err = ob_get_contents();
ob_end_clean();
if ($err != '')
QRtools::log($outfile, $err);
$maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
} catch (Exception $e) {
QRtools::log($outfile, $e->getMessage());
}
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/ServerInfo.class.php'
<?php
/**
* 服务器信息
* CPU、内存使用率
*/
class ServerInfo {
private $sysOs;
function __construct() {
$phpos = strtoupper(PHP_OS); // PHP_OS_FAMILY
if (substr($phpos, 0, 3) === 'WIN') {
$this->sysOs = 'win';
} elseif (substr($phpos, 0, 6) === 'DARWIN') {
$this->sysOs = 'mac';
} else {
$this->sysOs = 'linux';
}
}
public function cpuUsage(){
$action = 'cpuUsage'.ucfirst($this->sysOs);
return $this->$action();
}
public function memUsage(){
$action = 'memUsage'.ucfirst($this->sysOs);
return $this->$action();
}
// 获取/proc/xx文件内容
private static function getFileContent($file){
static $readList = array();
if (!isset($readList[$file])) {
$readList[$file] = @is_readable($file);
}
if ($readList[$file]) {
return @file_get_contents($file) ?: '';
}
return shell_exec('cat '.escapeShell($file)) ?: '';
}
/**
* cpu使用率-linux
* @return void
*/
public function cpuUsageLinux(){
$filePath = '/proc/stat';
$stat1 = self::getFileContent($filePath);
if (!$stat1) return 0;
$info1 = $this->parseCpuInfo($stat1);
sleep(1);
$stat2 = self::getFileContent($filePath);
$info2 = $this->parseCpuInfo($stat2);
// 确保有足够数据(至少4个字段:user, nice, system, idle)
if (count($info1) < 4 || count($info2) < 4) return 0;
$dif = array(
'user' => $info2[0] - $info1[0],
'nice' => $info2[1] - $info1[1],
'sys' => $info2[2] - $info1[2],
'idle' => $info2[3] - $info1[3],
);
$total = array_sum($dif);
return $total > 0 ? round(($total - $dif['idle']) / $total, 3) : 0;
}
private function parseCpuInfo($stat) {
$statLines = explode("\n", $stat);
$cpuLine = $statLines[0]; // 第一行是总CPU信息
return preg_split('/\s+/', trim(substr($cpuLine, 3))); // 去除"cpu"前缀
}
/**
* 内存使用率-linux
* @return void
*/
public function memUsageLinux(){
$data = array(
'total' => self::getMemoryUsage('MemTotal'),
'used' => self::getMemoryUsage('MemRealUsage'),
);
return $data;
}
/**
* cpu使用率-win
* @return void
*/
public function cpuUsageWin(){
$str = shell_exec('powershell "Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average | Select-Object -ExpandProperty Average"');
$str = trim($str);
return $str != '' ? round(floatval($str)/100, 3) : 0;
// return trim($str) . '%';
}
/**
* 内存使用率-win
* @return void
*/
public function memUsageWin(){
$str = shell_exec('powershell "Get-CimInstance Win32_OperatingSystem | FL TotalVisibleMemorySize,FreePhysicalMemory"');
$total = $free = 0;
foreach (explode("\n", trim($str)) as $line) {
if (preg_match('/^TotalVisibleMemorySize\s*:\s*(\d+)$/i', $line, $matches)) {
$total = (float)$matches[1];
} elseif (preg_match('/FreePhysicalMemory\s*:\s*(\d+)/i', $line, $matches)) {
$free = (float)$matches[1];
}
}
$data = array(
'total' => $total * 1024,
'used' => ($total - $free) * 1024,
);
// $data['percent'] = !$data['total'] ? '0%' : sprintf("%.1f",$data['used']/$data['total']*100).'%';
return $data;
}
public static function getMemoryUsage($key){
$key = ucfirst($key);
static $memInfo = null;
if (null === $memInfo) {
$memInfoFile = '/proc/meminfo';
$memInfo = self::getFileContent($memInfoFile);
if (!$memInfo) {
$memInfo = array();
return 0;
}
$memInfo = str_replace(array(
' kB',
' ',
), '', $memInfo);
$lines = array();
foreach (explode("\n", $memInfo) as $line) {
if (!$line) {
continue;
}
$line = explode(':', $line);
$lines[$line[0]] = (float)$line[1] * 1024;
}
$memInfo = $lines;
}
if (!isset($memInfo['MemTotal'])){
return 0;
}
switch ($key) {
case 'MemRealUsage':
if (isset($memInfo['MemAvailable'])) {
return $memInfo['MemTotal'] - $memInfo['MemAvailable'];
}
if (isset($memInfo['MemFree'])) {
$buffers = _get($memInfo, 'Buffers', 0);
$cached = _get($memInfo, 'Cached', 0);
$memFree = _get($memInfo, 'MemFree', 0);
return $memInfo['MemTotal'] - $memFree - $buffers - $cached;
}
return 0;
case 'MemUsage':
return isset($memInfo['MemFree']) ? $memInfo['MemTotal'] - $memInfo['MemFree'] : 0;
case 'SwapUsage':
if ( ! isset($memInfo['SwapTotal']) || ! isset($memInfo['SwapFree'])) {
return 0;
}
return $memInfo['SwapTotal'] - $memInfo['SwapFree'];
}
return isset($memInfo[$key]) ? $memInfo[$key] : 0;
}
/**
* cpu使用率-mac
* @return float
*/
public function cpuUsageMac() {
$cmd = "top -l 1 | grep -E '^CPU'";
$output = shell_exec($cmd);
if (preg_match('/(\d+\.\d+)% idle/', $output, $matches)) {
$idlePercent = floatval($matches[1]);
return round((100 - $idlePercent) / 100, 3);
}
return 0;
}
/**
* 内存使用率-mac
* @return array
*/
public function memUsageMac() {
$data = array(
'total' => 0,
'used' => 0,
);
// 获取总内存
$cmd = "/usr/sbin/sysctl -n hw.memsize";
$totalMemory = intval(shell_exec($cmd));
if ($totalMemory <= 0) {return $data;}
// 获取内存统计
$output = shell_exec("vm_stat");
if (!$output) {return $data;}
// 获取页面大小
preg_match('/page size of (\d+) bytes/i', $output, $matches);
$pageSize = !empty($matches[1]) ? intval($matches[1]) : 4096; // 默认页面大小
// 解析内存统计信息
$stats = array();
foreach (explode("\n", $output) as $line) {
if (preg_match('/^(Pages\s+(?:wired|active|inactive|speculative|free|throttled|compressed|purgeable))[^:]*:\s*([\d,]+)/i', $line, $matches)) {
$key = strtolower(preg_replace('/\s+/', '_', $matches[1]));
$stats[$key] = (int) str_replace(',', '', $matches[2]);
}
}
// 计算已使用内存
$wired = _get($stats, 'pages_wired', 0);
$compressed = _get($stats, 'pages_compressed', 0);
$active = _get($stats, 'pages_active', 0);
$inactive = _get($stats, 'pages_inactive', 0);
$purgeable = _get($stats, 'pages_purgeable', 0);
// 计算实际使用量
$appMemory = ($active + $inactive - $purgeable);
$usedPages = $wired + $compressed + $appMemory;
return array(
'total' => $totalMemory,
'used' => $usedPages * $pageSize
);
}
}
wget 'https://sme10.lists2.roe3.org/kodbox/app/sdks/lessc.class.php'
<?php
/**
* lessphp v0.5.0
* http://leafo.net/lessphp
*
* LESS CSS compiler, adapted from http://lesscss.org
*
* Copyright 2013, Leaf Corcoran <leafot@gmail.com>
* Licensed under MIT or GPLv3, see LICENSE
*/
/**
* The LESS compiler and parser.
*
* Converting LESS to CSS is a three stage process. The incoming file is parsed
* by `lessc_parser` into a syntax tree, then it is compiled into another tree
* representing the CSS structure by `lessc`. The CSS tree is fed into a
* formatter, like `lessc_formatter` which then outputs CSS as a string.
*
* During the first compile, all values are *reduced*, which means that their
* types are brought to the lowest form before being dump as strings. This
* handles math equations, variable dereferences, and the like.
*
* The `parse` function of `lessc` is the entry point.
*
* In summary:
*
* The `lessc` class creates an instance of the parser, feeds it LESS code,
* then transforms the resulting tree to a CSS tree. This class also holds the
* evaluation context, such as all available mixins and variables at any given
* time.
*
* The `lessc_parser` class is only concerned with parsing its input.
*
* The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
* handling things like indentation.
*/
class lessc {
static public $VERSION = "v0.5.0";
static public $TRUE = array("keyword", "true");
static public $FALSE = array("keyword", "false");
protected $libFunctions = array();
protected $registeredVars = array();
protected $preserveComments = false;
public $vPrefix = '@'; // prefix of abstract properties
public $mPrefix = '$'; // prefix of abstract blocks
public $parentSelector = '&';
public $importDisabled = false;
public $importDir = '';
protected $numberPrecision = null;
protected $allParsedFiles = array();
// set to the parser that generated the current line when compiling
// so we know how to create error messages
protected $sourceParser = null;
protected $sourceLoc = null;
static protected $nextImportId = 0; // uniquely identify imports
// attempts to find the path of an import url, returns null for css files
protected function findImport($url) {
foreach ((array)$this->importDir as $dir) {
$full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
return $file;
}
}
return null;
}
protected function fileExists($name) {
return is_file($name);
}
public static function compressList($items, $delim) {
if (!isset($items[1]) && isset($items[0])) return $items[0];
else return array('list', $delim, $items);
}
public static function preg_quote($what) {
return preg_quote($what, '/');
}
protected function tryImport($importPath, $parentBlock, $out) {
if ($importPath[0] == "function" && $importPath[1] == "url") {
$importPath = $this->flattenList($importPath[2]);
}
$str = $this->coerceString($importPath);
if ($str === null) return false;
$url = $this->compileValue($this->lib_e($str));
// don't import if it ends in css
if (substr_compare($url, '.css', -4, 4) === 0) return false;
$realPath = $this->findImport($url);
if ($realPath === null) return false;
if ($this->importDisabled) {
return array(false, "/* import disabled */");
}
if (isset($this->allParsedFiles[realpath($realPath)])) {
return array(false, null);
}
$this->addParsedFile($realPath);
$parser = $this->makeParser($realPath);
$root = $parser->parse(file_get_contents($realPath));
// set the parents of all the block props
foreach ($root->props as $prop) {
if ($prop[0] == "block") {
$prop[1]->parent = $parentBlock;
}
}
// copy mixins into scope, set their parents
// bring blocks from import into current block
// TODO: need to mark the source parser these came from this file
foreach ($root->children as $childName => $child) {
if (isset($parentBlock->children[$childName])) {
$parentBlock->children[$childName] = array_merge(
$parentBlock->children[$childName],
$child);
} else {
$parentBlock->children[$childName] = $child;
}
}
$pi = pathinfo($realPath);
$dir = $pi["dirname"];
list($top, $bottom) = $this->sortProps($root->props, true);
$this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);
return array(true, $bottom, $parser, $dir);
}
protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
$oldSourceParser = $this->sourceParser;
$oldImport = $this->importDir;
// TODO: this is because the importDir api is stupid
$this->importDir = (array)$this->importDir;
array_unshift($this->importDir, $importDir);
foreach ($props as $prop) {
$this->compileProp($prop, $block, $out);
}
$this->importDir = $oldImport;
$this->sourceParser = $oldSourceParser;
}
/**
* Recursively compiles a block.
*
* A block is analogous to a CSS block in most cases. A single LESS document
* is encapsulated in a block when parsed, but it does not have parent tags
* so all of it's children appear on the root level when compiled.
*
* Blocks are made up of props and children.
*
* Props are property instructions, array tuples which describe an action
* to be taken, eg. write a property, set a variable, mixin a block.
*
* The children of a block are just all the blocks that are defined within.
* This is used to look up mixins when performing a mixin.
*
* Compiling the block involves pushing a fresh environment on the stack,
* and iterating through the props, compiling each one.
*
* See lessc::compileProp()
*
*/
protected function compileBlock($block) {
switch ($block->type) {
case "root":
$this->compileRoot($block);
break;
case null:
$this->compileCSSBlock($block);
break;
case "media":
$this->compileMedia($block);
break;
case "directive":
$name = "@" . $block->name;
if (!empty($block->value)) {
$name .= " " . $this->compileValue($this->reduce($block->value));
}
$this->compileNestedBlock($block, array($name));
break;
default:
$this->throwError("unknown block type: $block->type\n");
}
}
protected function compileCSSBlock($block) {
$env = $this->pushEnv();
$selectors = $this->compileSelectors($block->tags);
$env->selectors = $this->multiplySelectors($selectors);
$out = $this->makeOutputBlock(null, $env->selectors);
$this->scope->children[] = $out;
$this->compileProps($block, $out);
$block->scope = $env; // mixins carry scope with them!
$this->popEnv();
}
protected function compileMedia($media) {
$env = $this->pushEnv($media);
$parentScope = $this->mediaParent($this->scope);
$query = $this->compileMediaQuery($this->multiplyMedia($env));
$this->scope = $this->makeOutputBlock($media->type, array($query));
$parentScope->children[] = $this->scope;
$this->compileProps($media, $this->scope);
if (count($this->scope->lines) > 0) {
$orphanSelelectors = $this->findClosestSelectors();
if (!is_null($orphanSelelectors)) {
$orphan = $this->makeOutputBlock(null, $orphanSelelectors);
$orphan->lines = $this->scope->lines;
array_unshift($this->scope->children, $orphan);
$this->scope->lines = array();
}
}
$this->scope = $this->scope->parent;
$this->popEnv();
}
protected function mediaParent($scope) {
while (!empty($scope->parent)) {
if (!empty($scope->type) && $scope->type != "media") {
break;
}
$scope = $scope->parent;
}
return $scope;
}
protected function compileNestedBlock($block, $selectors) {
$this->pushEnv($block);
$this->scope = $this->makeOutputBlock($block->type, $selectors);
$this->scope->parent->children[] = $this->scope;
$this->compileProps($block, $this->scope);
$this->scope = $this->scope->parent;
$this->popEnv();
}
protected function compileRoot($root) {
$this->pushEnv();
$this->scope = $this->makeOutputBlock($root->type);
$this->compileProps($root, $this->scope);
$this->popEnv();
}
protected function compileProps($block, $out) {
foreach ($this->sortProps($block->props) as $prop) {
$this->compileProp($prop, $block, $out);
}
$out->lines = $this->deduplicate($out->lines);
}
/**
* Deduplicate lines in a block. Comments are not deduplicated. If a
* duplicate rule is detected, the comments immediately preceding each
* occurence are consolidated.
*/
protected function deduplicate($lines) {
$unique = array();
$comments = array();
foreach ($lines as $line) {
if (strpos($line, '/*') === 0) {
$comments[] = $line;
continue;
}
if (!in_array($line, $unique)) {
$unique[] = $line;
}
array_splice($unique, array_search($line, $unique), 0, $comments);
$comments = array();
}
return array_merge($unique, $comments);
}
protected function sortProps($props, $split = false) {
$vars = array();
$imports = array();
$other = array();
$stack = array();
foreach ($props as $prop) {
switch ($prop[0]) {
case "comment":
$stack[] = $prop;
break;
case "assign":
$stack[] = $prop;
if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
$vars = array_merge($vars, $stack);
} else {
$other = array_merge($other, $stack);
}
$stack = array();
break;
case "import":
$id = self::$nextImportId++;
$prop[] = $id;
$stack[] = $prop;
$imports = array_merge($imports, $stack);
$other[] = array("import_mixin", $id);
$stack = array();
break;
default:
$stack[] = $prop;
$other = array_merge($other, $stack);
$stack = array();
break;
}
}
$other = array_merge($other, $stack);
if ($split) {
return array(array_merge($imports, $vars), $other);
} else {
return array_merge($imports, $vars, $other);
}
}
protected function compileMediaQuery($queries) {
$compiledQueries = array();
foreach ($queries as $query) {
$parts = array();
foreach ($query as $q) {
switch ($q[0]) {
case "mediaType":
$parts[] = implode(" ", array_slice($q, 1));
break;
case "mediaExp":
if (isset($q[2])) {
$parts[] = "($q[1]: " .
$this->compileValue($this->reduce($q[2])) . ")";
} else {
$parts[] = "($q[1])";
}
break;
case "variable":
$parts[] = $this->compileValue($this->reduce($q));
break;
}
}
if (count($parts) > 0) {
$compiledQueries[] = implode(" and ", $parts);
}
}
$out = "@media";
if (!empty($parts)) {
$out .= " " .
implode($this->formatter->selectorSeparator, $compiledQueries);
}
return $out;
}
protected function multiplyMedia($env, $childQueries = null) {
if (is_null($env) ||
!empty($env->block->type) && $env->block->type != "media"
) {
return $childQueries;
}
// plain old block, skip
if (empty($env->block->type)) {
return $this->multiplyMedia($env->parent, $childQueries);
}
$out = array();
$queries = $env->block->queries;
if (is_null($childQueries)) {
$out = $queries;
} else {
foreach ($queries as $parent) {
foreach ($childQueries as $child) {
$out[] = array_merge($parent, $child);
}
}
}
return $this->multiplyMedia($env->parent, $out);
}
protected function expandParentSelectors(&$tag, $replace) {
$parts = explode("$&$", $tag);
$count = 0;
foreach ($parts as &$part) {
$part = str_replace($this->parentSelector, $replace, $part, $c);
$count += $c;
}
$tag = implode($this->parentSelector, $parts);
return $count;
}
protected function findClosestSelectors() {
$env = $this->env;
$selectors = null;
while ($env !== null) {
if (isset($env->selectors)) {
$selectors = $env->selectors;
break;
}
$env = $env->parent;
}
return $selectors;
}
// multiply $selectors against the nearest selectors in env
protected function multiplySelectors($selectors) {
// find parent selectors
$parentSelectors = $this->findClosestSelectors();
if (is_null($parentSelectors)) {
// kill parent reference in top level selector
foreach ($selectors as &$s) {
$this->expandParentSelectors($s, "");
}
return $selectors;
}
$out = array();
foreach ($parentSelectors as $parent) {
foreach ($selectors as $child) {
$count = $this->expandParentSelectors($child, $parent);
// don't prepend the parent tag if & was used
if ($count > 0) {
$out[] = trim($child);
} else {
$out[] = trim($parent . ' ' . $child);
}
}
}
return $out;
}
// reduces selector expressions
protected function compileSelectors($selectors) {
$out = array();
foreach ($selectors as $s) {
if (is_array($s)) {
list(, $value) = $s;
$out[] = trim($this->compileValue($this->reduce($value)));
} else {
$out[] = $s;
}
}
return $out;
}
protected function eq($left, $right) {
return $left == $right;
}
protected function patternMatch($block, $orderedArgs, $keywordArgs) {
// match the guards if it has them
// any one of the groups must have all its guards pass for a match
if (!empty($block->guards)) {
$groupPassed = false;
foreach ($block->guards as $guardGroup) {
foreach ($guardGroup as $guard) {
$this->pushEnv();
$this->zipSetArgs($block->args, $orderedArgs, $keywordArgs);
$negate = false;
if ($guard[0] == "negate") {
$guard = $guard[1];
$negate = true;
}
$passed = $this->reduce($guard) == self::$TRUE;
if ($negate) $passed = !$passed;
$this->popEnv();
if ($passed) {
$groupPassed = true;
} else {
$groupPassed = false;
break;
}
}
if ($groupPassed) break;
}
if (!$groupPassed) {
return false;
}
}
if (empty($block->args)) {
return $block->isVararg || empty($orderedArgs) && empty($keywordArgs);
}
$remainingArgs = $block->args;
if ($keywordArgs) {
$remainingArgs = array();
foreach ($block->args as $arg) {
if ($arg[0] == "arg" && isset($keywordArgs[$arg[1]])) {
continue;
}
$remainingArgs[] = $arg;
}
}
$i = -1; // no args
// try to match by arity or by argument literal
foreach ($remainingArgs as $i => $arg) {
switch ($arg[0]) {
case "lit":
if (empty($orderedArgs[$i]) || !$this->eq($arg[1], $orderedArgs[$i])) {
return false;
}
break;
case "arg":
// no arg and no default value
if (!isset($orderedArgs[$i]) && !isset($arg[2])) {
return false;
}
break;
case "rest":
$i--; // rest can be empty
break 2;
}
}
if ($block->isVararg) {
return true; // not having enough is handled above
} else {
$numMatched = $i + 1;
// greater than because default values always match
return $numMatched >= count($orderedArgs);
}
}
protected function patternMatchAll($blocks, $orderedArgs, $keywordArgs, $skip=array()) {
$matches = null;
foreach ($blocks as $block) {
// skip seen blocks that don't have arguments
if (isset($skip[$block->id]) && !isset($block->args)) {
continue;
}
if ($this->patternMatch($block, $orderedArgs, $keywordArgs)) {
$matches[] = $block;
}
}
return $matches;
}
// attempt to find blocks matched by path and args
protected function findBlocks($searchIn, $path, $orderedArgs, $keywordArgs, $seen=array()) {
if ($searchIn == null) return null;
if (isset($seen[$searchIn->id])) return null;
$seen[$searchIn->id] = true;
$name = $path[0];
if (isset($searchIn->children[$name])) {
$blocks = $searchIn->children[$name];
if (count($path) == 1) {
$matches = $this->patternMatchAll($blocks, $orderedArgs, $keywordArgs, $seen);
if (!empty($matches)) {
// This will return all blocks that match in the closest
// scope that has any matching block, like lessjs
return $matches;
}
} else {
$matches = array();
foreach ($blocks as $subBlock) {
$subMatches = $this->findBlocks($subBlock,
array_slice($path, 1), $orderedArgs, $keywordArgs, $seen);
if (!is_null($subMatches)) {
foreach ($subMatches as $sm) {
$matches[] = $sm;
}
}
}
return count($matches) > 0 ? $matches : null;
}
}
if ($searchIn->parent === $searchIn) return null;
return $this->findBlocks($searchIn->parent, $path, $orderedArgs, $keywordArgs, $seen);
}
// sets all argument names in $args to either the default value
// or the one passed in through $values
protected function zipSetArgs($args, $orderedValues, $keywordValues) {
$assignedValues = array();
$i = 0;
foreach ($args as $a) {
if ($a[0] == "arg") {
if (isset($keywordValues[$a[1]])) {
// has keyword arg
$value = $keywordValues[$a[1]];
} elseif (isset($orderedValues[$i])) {
// has ordered arg
$value = $orderedValues[$i];
$i++;
} elseif (isset($a[2])) {
// has default value
$value = $a[2];
} else {
$this->throwError("Failed to assign arg " . $a[1]);
$value = null; // :(
}
$value = $this->reduce($value);
$this->set($a[1], $value);
$assignedValues[] = $value;
} else {
// a lit
$i++;
}
}
// check for a rest
$last = end($args);
if (is_array($last) && $last[0] == "rest") {
$rest = array_slice($orderedValues, count($args) - 1);
$this->set($last[1], $this->reduce(array("list", " ", $rest)));
}
// wow is this the only true use of PHP's + operator for arrays?
$this->env->arguments = $assignedValues + $orderedValues;
}
// compile a prop and update $lines or $blocks appropriately
protected function compileProp($prop, $block, $out) {
// set error position context
$this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;
switch ($prop[0]) {
case 'assign':
list(, $name, $value) = $prop;
if ($name[0] == $this->vPrefix) {
$this->set($name, $value);
} else {
$out->lines[] = $this->formatter->property($name,
$this->compileValue($this->reduce($value)));
}
break;
case 'block':
list(, $child) = $prop;
$this->compileBlock($child);
break;
case 'mixin':
list(, $path, $args, $suffix) = $prop;
$orderedArgs = array();
$keywordArgs = array();
foreach ((array)$args as $arg) {
$argval = null;
switch ($arg[0]) {
case "arg":
if (!isset($arg[2])) {
$orderedArgs[] = $this->reduce(array("variable", $arg[1]));
} else {
$keywordArgs[$arg[1]] = $this->reduce($arg[2]);
}
break;
case "lit":
$orderedArgs[] = $this->reduce($arg[1]);
break;
default:
$this->throwError("Unknown arg type: " . $arg[0]);
}
}
$mixins = $this->findBlocks($block, $path, $orderedArgs, $keywordArgs);
if ($mixins === null) {
$this->throwError("{$prop[1][0]} is undefined");
}
foreach ($mixins as $mixin) {
if ($mixin === $block && !$orderedArgs) {
continue;
}
$haveScope = false;
if (isset($mixin->parent->scope)) {
$haveScope = true;
$mixinParentEnv = $this->pushEnv();
$mixinParentEnv->storeParent = $mixin->parent->scope;
}
$haveArgs = false;
if (isset($mixin->args)) {
$haveArgs = true;
$this->pushEnv();
$this->zipSetArgs($mixin->args, $orderedArgs, $keywordArgs);
}
$oldParent = $mixin->parent;
if ($mixin != $block) $mixin->parent = $block;
foreach ($this->sortProps($mixin->props) as $subProp) {
if ($suffix !== null &&
$subProp[0] == "assign" &&
is_string($subProp[1]) &&
$subProp[1][0] != $this->vPrefix
) {
$subProp[2] = array(
'list', ' ',
array($subProp[2], array('keyword', $suffix))
);
}
$this->compileProp($subProp, $mixin, $out);
}
$mixin->parent = $oldParent;
if ($haveArgs) $this->popEnv();
if ($haveScope) $this->popEnv();
}
break;
case 'raw':
$out->lines[] = $prop[1];
break;
case "directive":
list(, $name, $value) = $prop;
$out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
break;
case "comment":
$out->lines[] = $prop[1];
break;
case "import":
list(, $importPath, $importId) = $prop;
$importPath = $this->reduce($importPath);
if (!isset($this->env->imports)) {
$this->env->imports = array();
}
$result = $this->tryImport($importPath, $block, $out);
$this->env->imports[$importId] = $result === false ?
array(false, "@import " . $this->compileValue($importPath).";") :
$result;
break;
case "import_mixin":
list(,$importId) = $prop;
$import = $this->env->imports[$importId];
if ($import[0] === false) {
if (isset($import[1])) {
$out->lines[] = $import[1];
}
} else {
list(, $bottom, $parser, $importDir) = $import;
$this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
}
break;
default:
$this->throwError("unknown op: {$prop[0]}\n");
}
}
/**
* Compiles a primitive value into a CSS property value.
*
* Values in lessphp are typed by being wrapped in arrays, their format is
* typically:
*
* array(type, contents [, additional_contents]*)
*
* The input is expected to be reduced. This function will not work on
* things like expressions and variables.
*/
public function compileValue($value) {
switch ($value[0]) {
case 'list':
// [1] - delimiter
// [2] - array of values
return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
case 'raw_color':
if (!empty($this->formatter->compressColors)) {
return $this->compileValue($this->coerceColor($value));
}
return $value[1];
case 'keyword':
// [1] - the keyword
return $value[1];
case 'number':
list(, $num, $unit) = $value;
// [1] - the number
// [2] - the unit
if ($this->numberPrecision !== null) {
$num = round($num, $this->numberPrecision);
}
return $num . $unit;
case 'string':
// [1] - contents of string (includes quotes)
list(, $delim, $content) = $value;
foreach ($content as &$part) {
if (is_array($part)) {
$part = $this->compileValue($part);
}
}
return $delim . implode($content) . $delim;
case 'color':
// [1] - red component (either number or a %)
// [2] - green component
// [3] - blue component
// [4] - optional alpha component
list(, $r, $g, $b) = $value;
$r = round($r);
$g = round($g);
$b = round($b);
if (count($value) == 5 && $value[4] != 1) { // rgba
return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
}
$h = sprintf("#%02x%02x%02x", $r, $g, $b);
if (!empty($this->formatter->compressColors)) {
// Converting hex color to short notation (e.g. #003399 to #039)
if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
$h = '#' . $h[1] . $h[3] . $h[5];
}
}
return $h;
case 'function':
list(, $name, $args) = $value;
return $name.'('.$this->compileValue($args).')';
default: // assumed to be unit
$this->throwError("unknown value type: $value[0]");
}
}
protected function lib_pow($args) {
list($base, $exp) = $this->assertArgs($args, 2, "pow");
return pow($this->assertNumber($base), $this->assertNumber($exp));
}
protected function lib_pi() {
return pi();
}
protected function lib_replace($args) {
// var_dump($args);exit;
list($str,$from,$to) = $this->assertArgs($args, 3, "replace");
return str_replace($from[2][0],$to[2][0],$str[2][0]);
}
protected function lib_mod($args) {
list($a, $b) = $this->assertArgs($args, 2, "mod");
return $this->assertNumber($a) % $this->assertNumber($b);
}
protected function lib_tan($num) {
return tan($this->assertNumber($num));
}
protected function lib_sin($num) {
return sin($this->assertNumber($num));
}
protected function lib_cos($num) {
return cos($this->assertNumber($num));
}
protected function lib_atan($num) {
$num = atan($this->assertNumber($num));
return array("number", $num, "rad");
}
protected function lib_asin($num) {
$num = asin($this->assertNumber($num));
return array("number", $num, "rad");
}
protected function lib_acos($num) {
$num = acos($this->assertNumber($num));
return array("number", $num, "rad");
}
protected function lib_sqrt($num) {
return sqrt($this->assertNumber($num));
}
protected function lib_extract($value) {
list($list, $idx) = $this->assertArgs($value, 2, "extract");
$idx = $this->assertNumber($idx);
// 1 indexed
if ($list[0] == "list" && isset($list[2][$idx - 1])) {
return $list[2][$idx - 1];
}
}
protected function lib_isnumber($value) {
return $this->toBool($value[0] == "number");
}
protected function lib_isstring($value) {
return $this->toBool($value[0] == "string");
}
protected function lib_iscolor($value) {
return $this->toBool($this->coerceColor($value));
}
protected function lib_iskeyword($value) {
return $this->toBool($value[0] == "keyword");
}
protected function lib_ispixel($value) {
return $this->toBool($value[0] == "number" && $value[2] == "px");
}
protected function lib_ispercentage($value) {
return $this->toBool($value[0] == "number" && $value[2] == "%");
}
protected function lib_isem($value) {
return $this->toBool($value[0] == "number" && $value[2] == "em");
}
protected function lib_isrem($value) {
return $this->toBool($value[0] == "number" && $value[2] == "rem");
}
protected function lib_rgbahex($color) {
$color = $this->coerceColor($color);
if (is_null($color)) {
$this->throwError("color expected for rgbahex");
}
return sprintf("#%02x%02x%02x%02x",
isset($color[4]) ? $color[4] * 255 : 255,
$color[1],
$color[2],
$color[3]
);
}
protected function lib_argb($color){
return $this->lib_rgbahex($color);
}
/**
* Given an url, decide whether to output a regular link or the base64-encoded contents of the file
*
* @param array $value either an argument list (two strings) or a single string
* @return string formatted url(), either as a link or base64-encoded
*/
protected function lib_data_uri($value) {
$mime = ($value[0] === 'list') ? $value[2][0][2] : null;
$url = ($value[0] === 'list') ? $value[2][1][2][0] : $value[2][0];
$fullpath = $this->findImport($url);
if ($fullpath && ($fsize = filesize($fullpath)) !== false) {
// IE8 can't handle data uris larger than 32KB
if ($fsize/1024 < 32) {
if (is_null($mime)) {
if (class_exists('finfo')) { // php 5.3+
$finfo = new finfo(FILEINFO_MIME);
$mime = explode('; ', $finfo->file($fullpath));
$mime = $mime[0];
} elseif (function_exists('mime_content_type')) { // PHP 5.2
$mime = mime_content_type($fullpath);
}
}
if (!is_null($mime)) // fallback if the mime type is still unknown
$url = sprintf('data:%s;base64,%s', $mime, base64_encode(file_get_contents($fullpath)));
}
}
return 'url("'.$url.'")';
}
// utility func to unquote a string
protected function lib_e($arg) {
switch ($arg[0]) {
case "list":
$items = $arg[2];
if (isset($items[0])) {
return $this->lib_e($items[0]);
}
$this->throwError("unrecognised input");
case "string":
$arg[1] = "";
return $arg;
case "keyword":
return $arg;
default:
return array("keyword", $this->compileValue($arg));
}
}
protected function lib__sprintf($args) {
if ($args[0] != "list") return $args;
$values = $args[2];
$string = array_shift($values);
$template = $this->compileValue($this->lib_e($string));
$i = 0;
if (preg_match_all('/%[dsa]/', $template, $m)) {
foreach ($m[0] as $match) {
$val = isset($values[$i]) ?
$this->reduce($values[$i]) : array('keyword', '');
// lessjs compat, renders fully expanded color, not raw color
if ($color = $this->coerceColor($val)) {
$val = $color;
}
$i++;
$rep = $this->compileValue($this->lib_e($val));
$template = preg_replace('/'.self::preg_quote($match).'/',
$rep, $template, 1);
}
}
$d = $string[0] == "string" ? $string[1] : '"';
return array("string", $d, array($template));
}
protected function lib_floor($arg) {
$value = $this->assertNumber($arg);
return array("number", floor($value), $arg[2]);
}
protected function lib_ceil($arg) {
$value = $this->assertNumber($arg);
return array("number", ceil($value), $arg[2]);
}
protected function lib_round($arg) {
if ($arg[0] != "list") {
$value = $this->assertNumber($arg);
return array("number", round($value), $arg[2]);
} else {
$value = $this->assertNumber($arg[2][0]);
$precision = $this->assertNumber($arg[2][1]);
return array("number", round($value, $precision), $arg[2][0][2]);
}
}
protected function lib_unit($arg) {
if ($arg[0] == "list") {
list($number, $newUnit) = $arg[2];
return array("number", $this->assertNumber($number),
$this->compileValue($this->lib_e($newUnit)));
} else {
return array("number", $this->assertNumber($arg), "");
}
}
/**
* Helper function to get arguments for color manipulation functions.
* takes a list that contains a color like thing and a percentage
*/
public function colorArgs($args) {
if ($args[0] != 'list' || count($args[2]) < 2) {
return array(array('color', 0, 0, 0), 0);
}
list($color, $delta) = $args[2];
$color = $this->assertColor($color);
$delta = floatval($delta[1]);
return array($color, $delta);
}
protected function lib_darken($args) {
list($color, $delta) = $this->colorArgs($args);
$hsl = $this->toHSL($color);
$hsl[3] = $this->clamp($hsl[3] - $delta, 100);
return $this->toRGB($hsl);
}
protected function lib_lighten($args) {
list($color, $delta) = $this->colorArgs($args);
$hsl = $this->toHSL($color);
$hsl[3] = $this->clamp($hsl[3] + $delta, 100);
return $this->toRGB($hsl);
}
protected function lib_saturate($args) {
list($color, $delta) = $this->colorArgs($args);
$hsl = $this->toHSL($color);
$hsl[2] = $this->clamp($hsl[2] + $delta, 100);
return $this->toRGB($hsl);
}
protected function lib_desaturate($args) {
list($color, $delta) = $this->colorArgs($args);
$hsl = $this->toHSL($color);
$hsl[2] = $this->clamp($hsl[2] - $delta, 100);
return $this->toRGB($hsl);
}
protected function lib_spin($args) {
list($color, $delta) = $this->colorArgs($args);
$hsl = $this->toHSL($color);
$hsl[1] = $hsl[1] + $delta % 360;
if ($hsl[1] < 0) {
$hsl[1] += 360;
}
return $this->toRGB($hsl);
}
protected function lib_fadeout($args) {
list($color, $delta) = $this->colorArgs($args);
$color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
return $color;
}
protected function lib_fadein($args) {
list($color, $delta) = $this->colorArgs($args);
$color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
return $color;
}
protected function lib_hue($color) {
$hsl = $this->toHSL($this->assertColor($color));
return round($hsl[1]);
}
protected function lib_saturation($color) {
$hsl = $this->toHSL($this->assertColor($color));
return round($hsl[2]);
}
protected function lib_lightness($color) {
$hsl = $this->toHSL($this->assertColor($color));
return round($hsl[3]);
}
// get the alpha of a color
// defaults to 1 for non-colors or colors without an alpha
protected function lib_alpha($value) {
if (!is_null($color = $this->coerceColor($value))) {
return isset($color[4]) ? $color[4] : 1;
}
}
// set the alpha of the color
protected function lib_fade($args) {
list($color, $alpha) = $this->colorArgs($args);
$color[4] = $this->clamp($alpha / 100.0);
return $color;
}
protected function lib_percentage($arg) {
$num = $this->assertNumber($arg);
return array("number", $num*100, "%");
}
/**
* Mix color with white in variable proportion.
*
* It is the same as calling `mix(#ffffff, @color, @weight)`.
*
* tint(@color, [@weight: 50%]);
*
* http://lesscss.org/functions/#color-operations-tint
*
* @return array Color
*/
protected function lib_tint($args) {
$white = ['color', 255, 255, 255];
if ($args[0] == 'color') {
return $this->lib_mix([ 'list', ',', [$white, $args] ]);
} elseif ($args[0] == "list" && count($args[2]) == 2) {
return $this->lib_mix([ $args[0], $args[1], [$white, $args[2][0], $args[2][1]] ]);
} else {
$this->throwError("tint expects (color, weight)");
}
}
/**
* Mix color with black in variable proportion.
*
* It is the same as calling `mix(#000000, @color, @weight)`
*
* shade(@color, [@weight: 50%]);
*
* http://lesscss.org/functions/#color-operations-shade
*
* @return array Color
*/
protected function lib_shade($args) {
$black = ['color', 0, 0, 0];
if ($args[0] == 'color') {
return $this->lib_mix([ 'list', ',', [$black, $args] ]);
} elseif ($args[0] == "list" && count($args[2]) == 2) {
return $this->lib_mix([ $args[0], $args[1], [$black, $args[2][0], $args[2][1]] ]);
} else {
$this->throwError("shade expects (color, weight)");
}
}
// mixes two colors by weight
// mix(@color1, @color2, [@weight: 50%]);
// http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
protected function lib_mix($args) {
if ($args[0] != "list" || count($args[2]) < 2)
$this->throwError("mix expects (color1, color2, weight)");
list($first, $second) = $args[2];
$first = $this->assertColor($first);
$second = $this->assertColor($second);
$first_a = $this->lib_alpha($first);
$second_a = $this->lib_alpha($second);
if (isset($args[2][2])) {
$weight = $args[2][2][1] / 100.0;
} else {
$weight = 0.5;
}
$w = $weight * 2 - 1;
$a = $first_a - $second_a;
$w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
$w2 = 1.0 - $w1;
$new = array('color',
$w1 * $first[1] + $w2 * $second[1],
$w1 * $first[2] + $w2 * $second[2],
$w1 * $first[3] + $w2 * $second[3],
);
if ($first_a != 1.0 || $second_a != 1.0) {
$new[] = $first_a * $weight + $second_a * ($weight - 1);
}
return $this->fixColor($new);
}
protected function lib_contrast($args) {
$darkColor = array('color', 0, 0, 0);
$lightColor = array('color', 255, 255, 255);
$threshold = 0.43;
if ( $args[0] == 'list' ) {
$inputColor = ( isset($args[2][0]) ) ? $this->assertColor($args[2][0]) : $lightColor;
$darkColor = ( isset($args[2][1]) ) ? $this->assertColor($args[2][1]) : $darkColor;
$lightColor = ( isset($args[2][2]) ) ? $this->assertColor($args[2][2]) : $lightColor;
$threshold = ( isset($args[2][3]) ) ? $this->assertNumber($args[2][3]) : $threshold;
}
else {
$inputColor = $this->assertColor($args);
}
$inputColor = $this->coerceColor($inputColor);
$darkColor = $this->coerceColor($darkColor);
$lightColor = $this->coerceColor($lightColor);
//Figure out which is actually light and dark!
if ( $this->toLuma($darkColor) > $this->toLuma($lightColor) ) {
$t = $lightColor;
$lightColor = $darkColor;
$darkColor = $t;
}
$inputColor_alpha = $this->lib_alpha($inputColor);
if ( ( $this->toLuma($inputColor) * $inputColor_alpha) < $threshold) {
return $lightColor;
}
return $darkColor;
}
private function toLuma($color) {
list(, $r, $g, $b) = $this->coerceColor($color);
$r = $r / 255;
$g = $g / 255;
$b = $b / 255;
$r = ($r <= 0.03928) ? $r / 12.92 : pow((($r + 0.055) / 1.055), 2.4);
$g = ($g <= 0.03928) ? $g / 12.92 : pow((($g + 0.055) / 1.055), 2.4);
$b = ($b <= 0.03928) ? $b / 12.92 : pow((($b + 0.055) / 1.055), 2.4);
return (0.2126 * $r) + (0.7152 * $g) + (0.0722 * $b);
}
protected function lib_luma($color) {
return array("number", round($this->toLuma($color) * 100, 8), "%");
}
public function assertColor($value, $error = "expected color value") {
$color = $this->coerceColor($value);
if (is_null($color)) $this->throwError($error);
return $color;
}
public function assertNumber($value, $error = "expecting number") {
if ($value[0] == "number") return $value[1];
$this->throwError($error);
}
public function assertArgs($value, $expectedArgs, $name="") {
if ($expectedArgs == 1) {
return $value;
} else {
if ($value[0] !== "list" || $value[1] != ",") $this->throwError("expecting list");
$values = $value[2];
$numValues = count($values);
if ($expectedArgs != $numValues) {
if ($name) {
$name = $name . ": ";
}
$this->throwError("${name}expecting $expectedArgs arguments, got $numValues");
}
return $values;
}
}
protected function toHSL($color) {
if ($color[0] === 'hsl') {
return $color;
}
$r = $color[1] / 255;
$g = $color[2] / 255;
$b = $color[3] / 255;
$min = min($r, $g, $b);
$max = max($r, $g, $b);
$L = ($min + $max) / 2;
if ($min == $max) {
$S = $H = 0;
} else {
if ($L < 0.5) {
$S = ($max - $min) / ($max + $min);
} else {
$S = ($max - $min) / (2.0 - $max - $min);
}
if ($r == $max) {
$H = ($g - $b) / ($max - $min);
} elseif ($g == $max) {
$H = 2.0 + ($b - $r) / ($max - $min);
} elseif ($b == $max) {
$H = 4.0 + ($r - $g) / ($max - $min);
}
}
$out = array('hsl',
($H < 0 ? $H + 6 : $H)*60,
$S * 100,
$L * 100,
);
if (count($color) > 4) {
// copy alpha
$out[] = $color[4];
}
return $out;
}
protected function toRGB_helper($comp, $temp1, $temp2) {
if ($comp < 0) {
$comp += 1.0;
} elseif ($comp > 1) {
$comp -= 1.0;
}
if (6 * $comp < 1) {
return $temp1 + ($temp2 - $temp1) * 6 * $comp;
}
if (2 * $comp < 1) {
return $temp2;
}
if (3 * $comp < 2) {
return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
}
return $temp1;
}
/**
* Converts a hsl array into a color value in rgb.
* Expects H to be in range of 0 to 360, S and L in 0 to 100
*/
protected function toRGB($color) {
if ($color[0] === 'color') {
return $color;
}
$H = $color[1] / 360;
$S = $color[2] / 100;
$L = $color[3] / 100;
if ($S == 0) {
$r = $g = $b = $L;
} else {
$temp2 = $L < 0.5 ?
$L * (1.0 + $S) :
$L + $S - $L * $S;
$temp1 = 2.0 * $L - $temp2;
$r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
$g = $this->toRGB_helper($H, $temp1, $temp2);
$b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
}
// $out = array('color', round($r*255), round($g*255), round($b*255));
$out = array('color', $r*255, $g*255, $b*255);
if (count($color) > 4) {
// copy alpha
$out[] = $color[4];
}
return $out;
}
protected function clamp($v, $max = 1, $min = 0) {
return min($max, max($min, $v));
}
/**
* Convert the rgb, rgba, hsl color literals of function type
* as returned by the parser into values of color type.
*/
protected function funcToColor($func) {
$fname = $func[1];
if ($func[2][0] != 'list') {
// need a list of arguments
return false;
}
$rawComponents = $func[2][2];
if ($fname == 'hsl' || $fname == 'hsla') {
$hsl = array('hsl');
$i = 0;
foreach ($rawComponents as $c) {
$val = $this->reduce($c);
$val = isset($val[1]) ? floatval($val[1]) : 0;
if ($i == 0) {
$clamp = 360;
} elseif ($i < 3) {
$clamp = 100;
} else {
$clamp = 1;
}
$hsl[] = $this->clamp($val, $clamp);
$i++;
}
while (count($hsl) < 4) {
$hsl[] = 0;
}
return $this->toRGB($hsl);
} elseif ($fname == 'rgb' || $fname == 'rgba') {
$components = array();
$i = 1;
foreach ($rawComponents as $c) {
$c = $this->reduce($c);
if ($i < 4) {
if ($c[0] == "number" && $c[2] == "%") {
$components[] = 255 * ($c[1] / 100);
} else {
$components[] = floatval($c[1]);
}
} elseif ($i == 4) {
if ($c[0] == "number" && $c[2] == "%") {
$components[] = 1.0 * ($c[1] / 100);
} else {
$components[] = floatval($c[1]);
}
} else break;
$i++;
}
while (count($components) < 3) {
$components[] = 0;
}
array_unshift($components, 'color');
return $this->fixColor($components);
}
return false;
}
protected function reduce($value, $forExpression = false) {
switch ($value[0]) {
case "interpolate":
$reduced = $this->reduce($value[1]);
$var = $this->compileValue($reduced);
$res = $this->reduce(array("variable", $this->vPrefix . $var));
if ($res[0] == "raw_color") {
$res = $this->coerceColor($res);
}
if (empty($value[2])) $res = $this->lib_e($res);
return $res;
case "variable":
$key = $value[1];
if (is_array($key)) {
$key = $this->reduce($key);
$key = $this->vPrefix . $this->compileValue($this->lib_e($key));
}
$seen =& $this->env->seenNames;
if (!empty($seen[$key])) {
$this->throwError("infinite loop detected: $key");
}
$seen[$key] = true;
$out = $this->reduce($this->get($key));
$seen[$key] = false;
return $out;
case "list":
foreach ($value[2] as &$item) {
$item = $this->reduce($item, $forExpression);
}
return $value;
case "expression":
return $this->evaluate($value);
case "string":
foreach ($value[2] as &$part) {
if (is_array($part)) {
$strip = $part[0] == "variable";
$part = $this->reduce($part);
if ($strip) $part = $this->lib_e($part);
}
}
return $value;
case "escape":
list(,$inner) = $value;
return $this->lib_e($this->reduce($inner));
case "function":
$color = $this->funcToColor($value);
if ($color) return $color;
list(, $name, $args) = $value;
if ($name == "%") $name = "_sprintf";
$f = isset($this->libFunctions[$name]) ?
$this->libFunctions[$name] : array($this, 'lib_'.str_replace('-', '_', $name));
if (is_callable($f)) {
if ($args[0] == 'list')
$args = self::compressList($args[2], $args[1]);
$ret = call_user_func($f, $this->reduce($args, true), $this);
if (is_null($ret)) {
return array("string", "", array(
$name, "(", $args, ")"
));
}
// convert to a typed value if the result is a php primitive
if (is_numeric($ret)) {
$ret = array('number', $ret, "");
} elseif (!is_array($ret)) {
$ret = array('keyword', $ret);
}
return $ret;
}
// plain function, reduce args
$value[2] = $this->reduce($value[2]);
return $value;
case "unary":
list(, $op, $exp) = $value;
$exp = $this->reduce($exp);
if ($exp[0] == "number") {
switch ($op) {
case "+":
return $exp;
case "-":
$exp[1] *= -1;
return $exp;
}
}
return array("string", "", array($op, $exp));
}
if ($forExpression) {
switch ($value[0]) {
case "keyword":
if ($color = $this->coerceColor($value)) {
return $color;
}
break;
case "raw_color":
return $this->coerceColor($value);
}
}
return $value;
}
// coerce a value for use in color operation
protected function coerceColor($value) {
switch ($value[0]) {
case 'color': return $value;
case 'raw_color':
$c = array("color", 0, 0, 0);
$colorStr = substr($value[1], 1);
$num = hexdec($colorStr);
$width = strlen($colorStr) == 3 ? 16 : 256;
for ($i = 3; $i > 0; $i--) { // 3 2 1
$t = intval($num) % $width;
$num /= $width;
$c[$i] = $t * (256/$width) + $t * floor(16/$width);
}
return $c;
case 'keyword':
$name = $value[1];
if (isset(self::$cssColors[$name])) {
$rgba = explode(',', self::$cssColors[$name]);
if (isset($rgba[3])) {
return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
}
return array('color', $rgba[0], $rgba[1], $rgba[2]);
}
return null;
}
}
// make something string like into a string
protected function coerceString($value) {
switch ($value[0]) {
case "string":
return $value;
case "keyword":
return array("string", "", array($value[1]));
}
return null;
}
// turn list of length 1 into value type
protected function flattenList($value) {
if ($value[0] == "list" && count($value[2]) == 1) {
return $this->flattenList($value[2][0]);
}
return $value;
}
public function toBool($a) {
return $a ? self::$TRUE : self::$FALSE;
}
// evaluate an expression
protected function evaluate($exp) {
list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;
$left = $this->reduce($left, true);
$right = $this->reduce($right, true);
if ($leftColor = $this->coerceColor($left)) {
$left = $leftColor;
}
if ($rightColor = $this->coerceColor($right)) {
$right = $rightColor;
}
$ltype = $left[0];
$rtype = $right[0];
// operators that work on all types
if ($op == "and") {
return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
}
if ($op == "=") {
return $this->toBool($this->eq($left, $right) );
}
if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) {
return $str;
}
// type based operators
$fname = "op_${ltype}_${rtype}";
if (is_callable(array($this, $fname))) {
$out = $this->$fname($op, $left, $right);
if (!is_null($out)) return $out;
}
// make the expression look it did before being parsed
$paddedOp = $op;
if ($whiteBefore) {
$paddedOp = " " . $paddedOp;
}
if ($whiteAfter) {
$paddedOp .= " ";
}
return array("string", "", array($left, $paddedOp, $right));
}
protected function stringConcatenate($left, $right) {
if ($strLeft = $this->coerceString($left)) {
if ($right[0] == "string") {
$right[1] = "";
}
$strLeft[2][] = $right;
return $strLeft;
}
if ($strRight = $this->coerceString($right)) {
array_unshift($strRight[2], $left);
return $strRight;
}
}
// make sure a color's components don't go out of bounds
protected function fixColor($c) {
foreach (range(1, 3) as $i) {
if ($c[$i] < 0) $c[$i] = 0;
if ($c[$i] > 255) $c[$i] = 255;
}
return $c;
}
protected function op_number_color($op, $lft, $rgt) {
if ($op == '+' || $op == '*') {
return $this->op_color_number($op, $rgt, $lft);
}
}
protected function op_color_number($op, $lft, $rgt) {
if ($rgt[0] == '%') $rgt[1] /= 100;
return $this->op_color_color($op, $lft,
array_fill(1, count($lft) - 1, $rgt[1]));
}
protected function op_color_color($op, $left, $right) {
$out = array('color');
$max = count($left) > count($right) ? count($left) : count($right);
foreach (range(1, $max - 1) as $i) {
$lval = isset($left[$i]) ? $left[$i] : 0;
$rval = isset($right[$i]) ? $right[$i] : 0;
switch ($op) {
case '+':
$out[] = $lval + $rval;
break;
case '-':
$out[] = $lval - $rval;
break;
case '*':
$out[] = $lval * $rval;
break;
case '%':
$out[] = $lval % $rval;
break;
case '/':
if ($rval == 0) {
$this->throwError("evaluate error: can't divide by zero");
}
$out[] = $lval / $rval;
break;
default:
$this->throwError('evaluate error: color op number failed on op '.$op);
}
}
return $this->fixColor($out);
}
public function lib_red($color){
$color = $this->coerceColor($color);
if (is_null($color)) {
$this->throwError('color expected for red()');
}
return $color[1];
}
public function lib_green($color){
$color = $this->coerceColor($color);
if (is_null($color)) {
$this->throwError('color expected for green()');
}
return $color[2];
}
public function lib_blue($color){
$color = $this->coerceColor($color);
if (is_null($color)) {
$this->throwError('color expected for blue()');
}
return $color[3];
}
// operator on two numbers
protected function op_number_number($op, $left, $right) {
$unit = empty($left[2]) ? $right[2] : $left[2];
$value = 0;
switch ($op) {
case '+':
$value = $left[1] + $right[1];
break;
case '*':
$value = $left[1] * $right[1];
break;
case '-':
$value = $left[1] - $right[1];
break;
case '%':
$value = $left[1] % $right[1];
break;
case '/':
if ($right[1] == 0) $this->throwError('parse error: divide by zero');
$value = $left[1] / $right[1];
break;
case '<':
return $this->toBool($left[1] < $right[1]);
case '>':
return $this->toBool($left[1] > $right[1]);
case '>=':
return $this->toBool($left[1] >= $right[1]);
case '=<':
return $this->toBool($left[1] <= $right[1]);
default:
$this->throwError('parse error: unknown number operator: '.$op);
}
return array("number", $value, $unit);
}
/* environment functions */
protected function makeOutputBlock($type, $selectors = null) {
$b = new stdclass;
$b->lines = array();
$b->children = array();
$b->selectors = $selectors;
$b->type = $type;
$b->parent = $this->scope;
return $b;
}
// the state of execution
protected function pushEnv($block = null) {
$e = new stdclass;
$e->parent = $this->env;
$e->store = array();
$e->block = $block;
$this->env = $e;
return $e;
}
// pop something off the stack
protected function popEnv() {
$old = $this->env;
$this->env = $this->env->parent;
return $old;
}
// set something in the current env
protected function set($name, $value) {
$this->env->store[$name] = $value;
}
// get the highest occurrence entry for a name
protected function get($name) {
$current = $this->env;
$isArguments = $name == $this->vPrefix . 'arguments';
while ($current) {
if ($isArguments && isset($current->arguments)) {
return array('list', ' ', $current->arguments);
}
if (isset($current->store[$name])) {
return $current->store[$name];
}
$current = isset($current->storeParent) ?
$current->storeParent :
$current->parent;
}
$this->throwError("variable $name is undefined");
}
// inject array of unparsed strings into environment as variables
protected function injectVariables($args) {
$this->pushEnv();
$parser = new lessc_parser($this, __METHOD__);
foreach ($args as $name => $strValue) {
if ($name[0] !== '@') {
$name = '@' . $name;
}
$parser->count = 0;
$parser->buffer = (string)$strValue;
if (!$parser->propertyValue($value)) {
throw new Exception("failed to parse passed in variable $name: $strValue");
}
$this->set($name, $value);
}
}
/**
* Initialize any static state, can initialize parser for a file
* $opts isn't used yet
*/
public function __construct($fname = null) {
if ($fname !== null) {
// used for deprecated parse method
$this->_parseFile = $fname;
}
}
public function compile($string, $name = null) {
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, "C");
$this->parser = $this->makeParser($name);
$root = $this->parser->parse($string);
$this->env = null;
$this->scope = null;
$this->formatter = $this->newFormatter();
if (!empty($this->registeredVars)) {
$this->injectVariables($this->registeredVars);
}
$this->sourceParser = $this->parser; // used for error messages
$this->compileBlock($root);
ob_start();
$this->formatter->block($this->scope);
$out = ob_get_clean();
setlocale(LC_NUMERIC, $locale);
return $out;
}
public function compileFile($fname, $outFname = null) {
if (!is_readable($fname)) {
throw new Exception('load error: failed to find '.$fname);
}
$pi = pathinfo($fname);
$oldImport = $this->importDir;
$this->importDir = (array)$this->importDir;
$this->importDir[] = $pi['dirname'].'/';
$this->addParsedFile($fname);
$out = $this->compile(file_get_contents($fname), $fname);
$this->importDir = $oldImport;
if ($outFname !== null) {
return file_put_contents($outFname, $out);
}
return $out;
}
// compile only if changed input has changed or output doesn't exist
public function checkedCompile($in, $out) {
if (!is_file($out) || filemtime($in) > filemtime($out)) {
$this->compileFile($in, $out);
return true;
}
return false;
}
/**
* Execute lessphp on a .less file or a lessphp cache structure
*
* The lessphp cache structure contains information about a specific
* less file having been parsed. It can be used as a hint for future
* calls to determine whether or not a rebuild is required.
*
* The cache structure contains two important keys that may be used
* externally:
*
* compiled: The final compiled CSS
* updated: The time (in seconds) the CSS was last compiled
*
* The cache structure is a plain-ol' PHP associative array and can
* be serialized and unserialized without a hitch.
*
* @param mixed $in Input
* @param bool $force Force rebuild?
* @return array lessphp cache structure
*/
public function cachedCompile($in, $force = false) {
// assume no root
$root = null;
if (is_string($in)) {
$root = $in;
} elseif (is_array($in) && isset($in['root'])) {
if ($force || !isset($in['files'])) {
// If we are forcing a recompile or if for some reason the
// structure does not contain any file information we should
// specify the root to trigger a rebuild.
$root = $in['root'];
} elseif (isset($in['files']) && is_array($in['files'])) {
foreach ($in['files'] as $fname => $ftime) {
if (!file_exists($fname) || filemtime($fname) > $ftime) {
// One of the files we knew about previously has changed
// so we should look at our incoming root again.
$root = $in['root'];
break;
}
}
}
} else {
// TODO: Throw an exception? We got neither a string nor something
// that looks like a compatible lessphp cache structure.
return null;
}
if ($root !== null) {
// If we have a root value which means we should rebuild.
$out = array();
$out['root'] = $root;
$out['compiled'] = $this->compileFile($root);
$out['files'] = $this->allParsedFiles();
$out['updated'] = time();
return $out;
} else {
// No changes, pass back the structure
// we were given initially.
return $in;
}
}
// parse and compile buffer
// This is deprecated
public function parse($str = null, $initialVariables = null) {
if (is_array($str)) {
$initialVariables = $str;
$str = null;
}
$oldVars = $this->registeredVars;
if ($initialVariables !== null) {
$this->setVariables($initialVariables);
}
if ($str == null) {
if (empty($this->_parseFile)) {
throw new exception("nothing to parse");
}
$out = $this->compileFile($this->_parseFile);
} else {
$out = $this->compile($str);
}
$this->registeredVars = $oldVars;
return $out;
}
protected function makeParser($name) {
$parser = new lessc_parser($this, $name);
$parser->writeComments = $this->preserveComments;
return $parser;
}
public function setFormatter($name) {
$this->formatterName = $name;
}
protected function newFormatter() {
$className = "lessc_formatter_lessjs";
if (!empty($this->formatterName)) {
if (!is_string($this->formatterName))
return $this->formatterName;
$className = "lessc_formatter_$this->formatterName";
}
return new $className;
}
public function setPreserveComments($preserve) {
$this->preserveComments = $preserve;
}
public function registerFunction($name, $func) {
$this->libFunctions[$name] = $func;
}
public function unregisterFunction($name) {
unset($this->libFunctions[$name]);
}
public function setVariables($variables) {
$this->registeredVars = array_merge($this->registeredVars, $variables);
}
public function unsetVariable($name) {
unset($this->registeredVars[$name]);
}
public function setImportDir($dirs) {
$this->importDir = (array)$dirs;
}
public function addImportDir($dir) {
$this->importDir = (array)$this->importDir;
$this->importDir[] = $dir;
}
public function allParsedFiles() {
return $this->allParsedFiles;
}
public function addParsedFile($file) {
$this->allParsedFiles[realpath($file)] = filemtime($file);
}
/**
* Uses the current value of $this->count to show line and line number
*/
public function throwError($msg = null) {
if ($this->sourceLoc >= 0) {
$this->sourceParser->throwError($msg, $this->sourceLoc);
}
throw new exception($msg);
}
// compile file $in to file $out if $in is newer than $out
// returns true when it compiles, false otherwise
public static function ccompile($in, $out, $less = null) {
if ($less === null) {
$less = new self;
}
return $less->checkedCompile($in, $out);
}
public static function cexecute($in, $force = false, $less = null) {
if ($less === null) {
$less = new self;
}
return $less->cachedCompile($in, $force);
}
static protected $cssColors = array(
'aliceblue' => '240,248,255',
'antiquewhite' => '250,235,215',
'aqua' => '0,255,255',
'aquamarine' => '127,255,212',
'azure' => '240,255,255',
'beige' => '245,245,220',
'bisque' => '255,228,196',
'black' => '0,0,0',
'blanchedalmond' => '255,235,205',
'blue' => '0,0,255',
'blueviolet' => '138,43,226',
'brown' => '165,42,42',
'burlywood' => '222,184,135',
'cadetblue' => '95,158,160',
'chartreuse' => '127,255,0',
'chocolate' => '210,105,30',
'coral' => '255,127,80',
'cornflowerblue' => '100,149,237',
'cornsilk' => '255,248,220',
'crimson' => '220,20,60',
'cyan' => '0,255,255',
'darkblue' => '0,0,139',
'darkcyan' => '0,139,139',
'darkgoldenrod' => '184,134,11',
'darkgray' => '169,169,169',
'darkgreen' => '0,100,0',
'darkgrey' => '169,169,169',
'darkkhaki' => '189,183,107',
'darkmagenta' => '139,0,139',
'darkolivegreen' => '85,107,47',
'darkorange' => '255,140,0',
'darkorchid' => '153,50,204',
'darkred' => '139,0,0',
'darksalmon' => '233,150,122',
'darkseagreen' => '143,188,143',
'darkslateblue' => '72,61,139',
'darkslategray' => '47,79,79',
'darkslategrey' => '47,79,79',
'darkturquoise' => '0,206,209',
'darkviolet' => '148,0,211',
'deeppink' => '255,20,147',
'deepskyblue' => '0,191,255',
'dimgray' => '105,105,105',
'dimgrey' => '105,105,105',
'dodgerblue' => '30,144,255',
'firebrick' => '178,34,34',
'floralwhite' => '255,250,240',
'forestgreen' => '34,139,34',
'fuchsia' => '255,0,255',
'gainsboro' => '220,220,220',
'ghostwhite' => '248,248,255',
'gold' => '255,215,0',
'goldenrod' => '218,165,32',
'gray' => '128,128,128',
'green' => '0,128,0',
'greenyellow' => '173,255,47',
'grey' => '128,128,128',
'honeydew' => '240,255,240',
'hotpink' => '255,105,180',
'indianred' => '205,92,92',
'indigo' => '75,0,130',
'ivory' => '255,255,240',
'khaki' => '240,230,140',
'lavender' => '230,230,250',
'lavenderblush' => '255,240,245',
'lawngreen' => '124,252,0',
'lemonchiffon' => '255,250,205',
'lightblue' => '173,216,230',
'lightcoral' => '240,128,128',
'lightcyan' => '224,255,255',
'lightgoldenrodyellow' => '250,250,210',
'lightgray' => '211,211,211',
'lightgreen' => '144,238,144',
'lightgrey' => '211,211,211',
'lightpink' => '255,182,193',
'lightsalmon' => '255,160,122',
'lightseagreen' => '32,178,170',
'lightskyblue' => '135,206,250',
'lightslategray' => '119,136,153',
'lightslategrey' => '119,136,153',
'lightsteelblue' => '176,196,222',
'lightyellow' => '255,255,224',
'lime' => '0,255,0',
'limegreen' => '50,205,50',
'linen' => '250,240,230',
'magenta' => '255,0,255',
'maroon' => '128,0,0',
'mediumaquamarine' => '102,205,170',
'mediumblue' => '0,0,205',
'mediumorchid' => '186,85,211',
'mediumpurple' => '147,112,219',
'mediumseagreen' => '60,179,113',
'mediumslateblue' => '123,104,238',
'mediumspringgreen' => '0,250,154',
'mediumturquoise' => '72,209,204',
'mediumvioletred' => '199,21,133',
'midnightblue' => '25,25,112',
'mintcream' => '245,255,250',
'mistyrose' => '255,228,225',
'moccasin' => '255,228,181',
'navajowhite' => '255,222,173',
'navy' => '0,0,128',
'oldlace' => '253,245,230',
'olive' => '128,128,0',
'olivedrab' => '107,142,35',
'orange' => '255,165,0',
'orangered' => '255,69,0',
'orchid' => '218,112,214',
'palegoldenrod' => '238,232,170',
'palegreen' => '152,251,152',
'paleturquoise' => '175,238,238',
'palevioletred' => '219,112,147',
'papayawhip' => '255,239,213',
'peachpuff' => '255,218,185',
'peru' => '205,133,63',
'pink' => '255,192,203',
'plum' => '221,160,221',
'powderblue' => '176,224,230',
'purple' => '128,0,128',
'red' => '255,0,0',
'rosybrown' => '188,143,143',
'royalblue' => '65,105,225',
'saddlebrown' => '139,69,19',
'salmon' => '250,128,114',
'sandybrown' => '244,164,96',
'seagreen' => '46,139,87',
'seashell' => '255,245,238',
'sienna' => '160,82,45',
'silver' => '192,192,192',
'skyblue' => '135,206,235',
'slateblue' => '106,90,205',
'slategray' => '112,128,144',
'slategrey' => '112,128,144',
'snow' => '255,250,250',
'springgreen' => '0,255,127',
'steelblue' => '70,130,180',
'tan' => '210,180,140',
'teal' => '0,128,128',
'thistle' => '216,191,216',
'tomato' => '255,99,71',
'transparent' => '0,0,0,0',
'turquoise' => '64,224,208',
'violet' => '238,130,238',
'wheat' => '245,222,179',
'white' => '255,255,255',
'whitesmoke' => '245,245,245',
'yellow' => '255,255,0',
'yellowgreen' => '154,205,50'
);
}
// responsible for taking a string of LESS code and converting it into a
// syntax tree
class lessc_parser {
static protected $nextBlockId = 0; // used to uniquely identify blocks
static protected $precedence = array(
'=<' => 0,
'>=' => 0,
'=' => 0,
'<' => 0,
'>' => 0,
'+' => 1,
'-' => 1,
'*' => 2,
'/' => 2,
'%' => 2,
);
static protected $whitePattern;
static protected $commentMulti;
static protected $commentSingle = "//";
static protected $commentMultiLeft = "/*";
static protected $commentMultiRight = "*/";
// regex string to match any of the operators
static protected $operatorString;
// these properties will supress division unless it's inside parenthases
static protected $supressDivisionProps =
array('/border-radius$/i', '/^font$/i');
protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
protected $lineDirectives = array("charset");
/**
* if we are in parens we can be more liberal with whitespace around
* operators because it must evaluate to a single value and thus is less
* ambiguous.
*
* Consider:
* property1: 10 -5; // is two numbers, 10 and -5
* property2: (10 -5); // should evaluate to 5
*/
protected $inParens = false;
// caches preg escaped literals
static protected $literalCache = array();
public function __construct($lessc, $sourceName = null) {
$this->eatWhiteDefault = true;
// reference to less needed for vPrefix, mPrefix, and parentSelector
$this->lessc = $lessc;
$this->sourceName = $sourceName; // name used for error messages
$this->writeComments = false;
if (!self::$operatorString) {
self::$operatorString =
'('.implode('|', array_map(array('lessc', 'preg_quote'),
array_keys(self::$precedence))).')';
$commentSingle = lessc::preg_quote(self::$commentSingle);
$commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
$commentMultiRight = lessc::preg_quote(self::$commentMultiRight);
self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
}
}
public function parse($buffer) {
$this->count = 0;
$this->line = 1;
$this->env = null; // block stack
$this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
$this->pushSpecialBlock("root");
$this->eatWhiteDefault = true;
$this->seenComments = array();
// trim whitespace on head
// if (preg_match('/^\s+/', $this->buffer, $m)) {
// $this->line += substr_count($m[0], "\n");
// $this->buffer = ltrim($this->buffer);
// }
$this->whitespace();
// parse the entire file
while (false !== $this->parseChunk());
if ($this->count != strlen($this->buffer))
$this->throwError();
// TODO report where the block was opened
if ( !property_exists($this->env, 'parent') || !is_null($this->env->parent) )
throw new exception('parse error: unclosed block');
return $this->env;
}
/**
* Parse a single chunk off the head of the buffer and append it to the
* current parse environment.
* Returns false when the buffer is empty, or when there is an error.
*
* This function is called repeatedly until the entire document is
* parsed.
*
* This parser is most similar to a recursive descent parser. Single
* functions represent discrete grammatical rules for the language, and
* they are able to capture the text that represents those rules.
*
* Consider the function lessc::keyword(). (all parse functions are
* structured the same)
*
* The function takes a single reference argument. When calling the
* function it will attempt to match a keyword on the head of the buffer.
* If it is successful, it will place the keyword in the referenced
* argument, advance the position in the buffer, and return true. If it
* fails then it won't advance the buffer and it will return false.
*
* All of these parse functions are powered by lessc::match(), which behaves
* the same way, but takes a literal regular expression. Sometimes it is
* more convenient to use match instead of creating a new function.
*
* Because of the format of the functions, to parse an entire string of
* grammatical rules, you can chain them together using &&.
*
* But, if some of the rules in the chain succeed before one fails, then
* the buffer position will be left at an invalid state. In order to
* avoid this, lessc::seek() is used to remember and set buffer positions.
*
* Before parsing a chain, use $s = $this->seek() to remember the current
* position into $s. Then if a chain fails, use $this->seek($s) to
* go back where we started.
*/
protected function parseChunk() {
if (empty($this->buffer)) return false;
$s = $this->seek();
if ($this->whitespace()) {
return true;
}
// setting a property
if ($this->keyword($key) && $this->assign() &&
$this->propertyValue($value, $key) && $this->end()
) {
$this->append(array('assign', $key, $value), $s);
return true;
} else {
$this->seek($s);
}
// look for special css blocks
if ($this->literal('@', false)) {
$this->count--;
// media
if ($this->literal('@media')) {
if (($this->mediaQueryList($mediaQueries) || true)
&& $this->literal('{')
) {
$media = $this->pushSpecialBlock("media");
$media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
return true;
} else {
$this->seek($s);
return false;
}
}
if ($this->literal("@", false) && $this->keyword($dirName)) {
if ($this->isDirective($dirName, $this->blockDirectives)) {
if (($this->openString("{", $dirValue, null, array(";")) || true) &&
$this->literal("{")
) {
$dir = $this->pushSpecialBlock("directive");
$dir->name = $dirName;
if (isset($dirValue)) $dir->value = $dirValue;
return true;
}
} elseif ($this->isDirective($dirName, $this->lineDirectives)) {
if ($this->propertyValue($dirValue) && $this->end()) {
$this->append(array("directive", $dirName, $dirValue));
return true;
}
}
}
$this->seek($s);
}
// setting a variable
if ($this->variable($var) && $this->assign() &&
$this->propertyValue($value) && $this->end()
) {
$this->append(array('assign', $var, $value), $s);
return true;
} else {
$this->seek($s);
}
if ($this->import($importValue)) {
$this->append($importValue, $s);
return true;
}
// opening parametric mixin
if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
($this->guards($guards) || true) &&
$this->literal('{')
) {
$block = $this->pushBlock($this->fixTags(array($tag)));
$block->args = $args;
$block->isVararg = $isVararg;
if (!empty($guards)) $block->guards = $guards;
return true;
} else {
$this->seek($s);
}
// opening a simple block
if ($this->tags($tags) && $this->literal('{', false)) {
$tags = $this->fixTags($tags);
$this->pushBlock($tags);
return true;
} else {
$this->seek($s);
}
// closing a block
if ($this->literal('}', false)) {
try {
$block = $this->pop();
} catch (exception $e) {
$this->seek($s);
$this->throwError($e->getMessage());
}
$hidden = false;
if (is_null($block->type)) {
$hidden = true;
if (!isset($block->args)) {
foreach ($block->tags as $tag) {
if (!is_string($tag) || $tag[0] != $this->lessc->mPrefix) {
$hidden = false;
break;
}
}
}
foreach ($block->tags as $tag) {
if (is_string($tag)) {
$this->env->children[$tag][] = $block;
}
}
}
if (!$hidden) {
$this->append(array('block', $block), $s);
}
// this is done here so comments aren't bundled into he block that
// was just closed
$this->whitespace();
return true;
}
// mixin
if ($this->mixinTags($tags) &&
($this->argumentDef($argv, $isVararg) || true) &&
($this->keyword($suffix) || true) && $this->end()
) {
$tags = $this->fixTags($tags);
$this->append(array('mixin', $tags, $argv, $suffix), $s);
return true;
} else {
$this->seek($s);
}
// spare ;
if ($this->literal(';')) return true;
return false; // got nothing, throw error
}
protected function isDirective($dirname, $directives) {
// TODO: cache pattern in parser
$pattern = implode("|",
array_map(array("lessc", "preg_quote"), $directives));
$pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
return preg_match($pattern, $dirname);
}
protected function fixTags($tags) {
// move @ tags out of variable namespace
foreach ($tags as &$tag) {
if ($tag[0] == $this->lessc->vPrefix)
$tag[0] = $this->lessc->mPrefix;
}
return $tags;
}
// a list of expressions
protected function expressionList(&$exps) {
$values = array();
while ($this->expression($exp)) {
$values[] = $exp;
}
if (count($values) == 0) return false;
$exps = lessc::compressList($values, ' ');
return true;
}
/**
* Attempt to consume an expression.
* @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
*/
protected function expression(&$out) {
if ($this->value($lhs)) {
$out = $this->expHelper($lhs, 0);
// look for / shorthand
if (!empty($this->env->supressedDivision)) {
unset($this->env->supressedDivision);
$s = $this->seek();
if ($this->literal("/") && $this->value($rhs)) {
$out = array("list", "",
array($out, array("keyword", "/"), $rhs));
} else {
$this->seek($s);
}
}
return true;
}
return false;
}
/**
* recursively parse infix equation with $lhs at precedence $minP
*/
protected function expHelper($lhs, $minP) {
$this->inExp = true;
$ss = $this->seek();
while (true) {
$whiteBefore = isset($this->buffer[$this->count - 1]) &&
ctype_space($this->buffer[$this->count - 1]);
// If there is whitespace before the operator, then we require
// whitespace after the operator for it to be an expression
$needWhite = $whiteBefore && !$this->inParens;
if ($this->matchReg(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
foreach (self::$supressDivisionProps as $pattern) {
if (preg_match($pattern, $this->env->currentProperty)) {
$this->env->supressedDivision = true;
break 2;
}
}
}
$whiteAfter = isset($this->buffer[$this->count - 1]) &&
ctype_space($this->buffer[$this->count - 1]);
if (!$this->value($rhs)) break;
// peek for next operator to see what to do with rhs
if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
$rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
}
$lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
$ss = $this->seek();
continue;
}
break;
}
$this->seek($ss);
return $lhs;
}
// consume a list of values for a property
public function propertyValue(&$value, $keyName = null) {
$values = array();
if ($keyName !== null) $this->env->currentProperty = $keyName;
$s = null;
while ($this->expressionList($v)) {
$values[] = $v;
$s = $this->seek();
if (!$this->literal(',')) break;
}
if ($s) $this->seek($s);
if ($keyName !== null) unset($this->env->currentProperty);
if (count($values) == 0) return false;
$value = lessc::compressList($values, ', ');
return true;
}
protected function parenValue(&$out) {
$s = $this->seek();
// speed shortcut
if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
return false;
}
$inParens = $this->inParens;
if ($this->literal("(") &&
($this->inParens = true) && $this->expression($exp) &&
$this->literal(")")
) {
$out = $exp;
$this->inParens = $inParens;
return true;
} else {
$this->inParens = $inParens;
$this->seek($s);
}
return false;
}
// a single value
protected function value(&$value) {
$s = $this->seek();
// speed shortcut
if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
// negation
if ($this->literal("-", false) &&
(($this->variable($inner) && $inner = array("variable", $inner)) ||
$this->unit($inner) ||
$this->parenValue($inner))
) {
$value = array("unary", "-", $inner);
return true;
} else {
$this->seek($s);
}
}
if ($this->parenValue($value)) return true;
if ($this->unit($value)) return true;
if ($this->color($value)) return true;
if ($this->func($value)) return true;
if ($this->string($value)) return true;
if ($this->keyword($word)) {
$value = array('keyword', $word);
return true;
}
// try a variable
if ($this->variable($var)) {
$value = array('variable', $var);
return true;
}
// unquote string (should this work on any type?
if ($this->literal("~") && $this->string($str)) {
$value = array("escape", $str);
return true;
} else {
$this->seek($s);
}
// css hack: \0
if ($this->literal('\\') && $this->matchReg('([0-9]+)', $m)) {
$value = array('keyword', '\\'.$m[1]);
return true;
} else {
$this->seek($s);
}
return false;
}
// an import statement
protected function import(&$out) {
if (!$this->literal('@import')) return false;
// @import "something.css" media;
// @import url("something.css") media;
// @import url(something.css) media;
if ($this->propertyValue($value)) {
$out = array("import", $value);
return true;
}
}
protected function mediaQueryList(&$out) {
if ($this->genericList($list, "mediaQuery", ",", false)) {
$out = $list[2];
return true;
}
return false;
}
protected function mediaQuery(&$out) {
$s = $this->seek();
$expressions = null;
$parts = array();
if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
$prop = array("mediaType");
if (isset($only)) $prop[] = "only";
if (isset($not)) $prop[] = "not";
$prop[] = $mediaType;
$parts[] = $prop;
} else {
$this->seek($s);
}
if (!empty($mediaType) && !$this->literal("and")) {
// ~
} else {
$this->genericList($expressions, "mediaExpression", "and", false);
if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
}
if (count($parts) == 0) {
$this->seek($s);
return false;
}
$out = $parts;
return true;
}
protected function mediaExpression(&$out) {
$s = $this->seek();
$value = null;
if ($this->literal("(") &&
$this->keyword($feature) &&
($this->literal(":") && $this->expression($value) || true) &&
$this->literal(")")
) {
$out = array("mediaExp", $feature);
if ($value) $out[] = $value;
return true;
} elseif ($this->variable($variable)) {
$out = array('variable', $variable);
return true;
}
$this->seek($s);
return false;
}
// an unbounded string stopped by $end
protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) {
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
$stop = array("'", '"', "@{", $end);
$stop = array_map(array("lessc", "preg_quote"), $stop);
// $stop[] = self::$commentMulti;
if (!is_null($rejectStrs)) {
$stop = array_merge($stop, $rejectStrs);
}
$patt = '(.*?)('.implode("|", $stop).')';
$nestingLevel = 0;
$content = array();
while ($this->matchReg($patt, $m, false)) {
if (!empty($m[1])) {
$content[] = $m[1];
if ($nestingOpen) {
$nestingLevel += substr_count($m[1], $nestingOpen);
}
}
$tok = $m[2];
$this->count-= strlen($tok);
if ($tok == $end) {
if ($nestingLevel == 0) {
break;
} else {
$nestingLevel--;
}
}
if (($tok == "'" || $tok == '"') && $this->string($str)) {
$content[] = $str;
continue;
}
if ($tok == "@{" && $this->interpolation($inter)) {
$content[] = $inter;
continue;
}
if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
break;
}
$content[] = $tok;
$this->count+= strlen($tok);
}
$this->eatWhiteDefault = $oldWhite;
if (count($content) == 0) return false;
// trim the end
if (is_string(end($content))) {
$content[count($content) - 1] = rtrim(end($content));
}
$out = array("string", "", $content);
return true;
}
protected function string(&$out) {
$s = $this->seek();
if ($this->literal('"', false)) {
$delim = '"';
} elseif ($this->literal("'", false)) {
$delim = "'";
} else {
return false;
}
$content = array();
// look for either ending delim , escape, or string interpolation
$patt = '([^\n]*?)(@\{|\\\\|' .
lessc::preg_quote($delim).')';
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
while ($this->matchReg($patt, $m, false)) {
$content[] = $m[1];
if ($m[2] == "@{") {
$this->count -= strlen($m[2]);
if ($this->interpolation($inter, false)) {
$content[] = $inter;
} else {
$this->count += strlen($m[2]);
$content[] = "@{"; // ignore it
}
} elseif ($m[2] == '\\') {
$content[] = $m[2];
if ($this->literal($delim, false)) {
$content[] = $delim;
}
} else {
$this->count -= strlen($delim);
break; // delim
}
}
$this->eatWhiteDefault = $oldWhite;
if ($this->literal($delim)) {
$out = array("string", $delim, $content);
return true;
}
$this->seek($s);
return false;
}
protected function interpolation(&$out) {
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = true;
$s = $this->seek();
if ($this->literal("@{") &&
$this->openString("}", $interp, null, array("'", '"', ";")) &&
$this->literal("}", false)
) {
$out = array("interpolate", $interp);
$this->eatWhiteDefault = $oldWhite;
if ($this->eatWhiteDefault) $this->whitespace();
return true;
}
$this->eatWhiteDefault = $oldWhite;
$this->seek($s);
return false;
}
protected function unit(&$unit) {
// speed shortcut
if (isset($this->buffer[$this->count])) {
$char = $this->buffer[$this->count];
if (!ctype_digit($char) && $char != ".") return false;
}
if ($this->matchReg('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
$unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
return true;
}
return false;
}
// a # color
protected function color(&$out) {
if ($this->matchReg('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
if (strlen($m[1]) > 7) {
$out = array("string", "", array($m[1]));
} else {
$out = array("raw_color", $m[1]);
}
return true;
}
return false;
}
// consume an argument definition list surrounded by ()
// each argument is a variable name with optional value
// or at the end a ... or a variable named followed by ...
// arguments are separated by , unless a ; is in the list, then ; is the
// delimiter.
protected function argumentDef(&$args, &$isVararg) {
$s = $this->seek();
if (!$this->literal('(')) {
return false;
}
$values = array();
$delim = ",";
$method = "expressionList";
$isVararg = false;
while (true) {
if ($this->literal("...")) {
$isVararg = true;
break;
}
if ($this->$method($value)) {
if ($value[0] == "variable") {
$arg = array("arg", $value[1]);
$ss = $this->seek();
if ($this->assign() && $this->$method($rhs)) {
$arg[] = $rhs;
} else {
$this->seek($ss);
if ($this->literal("...")) {
$arg[0] = "rest";
$isVararg = true;
}
}
$values[] = $arg;
if ($isVararg) {
break;
}
continue;
} else {
$values[] = array("lit", $value);
}
}
if (!$this->literal($delim)) {
if ($delim == "," && $this->literal(";")) {
// found new delim, convert existing args
$delim = ";";
$method = "propertyValue";
// transform arg list
if (isset($values[1])) { // 2 items
$newList = array();
foreach ($values as $i => $arg) {
switch ($arg[0]) {
case "arg":
if ($i) {
$this->throwError("Cannot mix ; and , as delimiter types");
}
$newList[] = $arg[2];
break;
case "lit":
$newList[] = $arg[1];
break;
case "rest":
$this->throwError("Unexpected rest before semicolon");
}
}
$newList = array("list", ", ", $newList);
switch ($values[0][0]) {
case "arg":
$newArg = array("arg", $values[0][1], $newList);
break;
case "lit":
$newArg = array("lit", $newList);
break;
}
} elseif ($values) { // 1 item
$newArg = $values[0];
}
if ($newArg) {
$values = array($newArg);
}
} else {
break;
}
}
}
if (!$this->literal(')')) {
$this->seek($s);
return false;
}
$args = $values;
return true;
}
// consume a list of tags
// this accepts a hanging delimiter
protected function tags(&$tags, $simple = false, $delim = ',') {
$tags = array();
while ($this->tag($tt, $simple)) {
$tags[] = $tt;
if (!$this->literal($delim)) break;
}
if (count($tags) == 0) return false;
return true;
}
// list of tags of specifying mixin path
// optionally separated by > (lazy, accepts extra >)
protected function mixinTags(&$tags) {
$tags = array();
while ($this->tag($tt, true)) {
$tags[] = $tt;
$this->literal(">");
}
if (!$tags) {
return false;
}
return true;
}
// a bracketed value (contained within in a tag definition)
protected function tagBracket(&$parts, &$hasExpression) {
// speed shortcut
if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
return false;
}
$s = $this->seek();
$hasInterpolation = false;
if ($this->literal("[", false)) {
$attrParts = array("[");
// keyword, string, operator
while (true) {
if ($this->literal("]", false)) {
$this->count--;
break; // get out early
}
if ($this->matchReg('\s+', $m)) {
$attrParts[] = " ";
continue;
}
if ($this->string($str)) {
// escape parent selector, (yuck)
foreach ($str[2] as &$chunk) {
$chunk = str_replace($this->lessc->parentSelector, "$&$", $chunk);
}
$attrParts[] = $str;
$hasInterpolation = true;
continue;
}
if ($this->keyword($word)) {
$attrParts[] = $word;
continue;
}
if ($this->interpolation($inter, false)) {
$attrParts[] = $inter;
$hasInterpolation = true;
continue;
}
// operator, handles attr namespace too
if ($this->matchReg('[|-~\$\*\^=]+', $m)) {
$attrParts[] = $m[0];
continue;
}
break;
}
if ($this->literal("]", false)) {
$attrParts[] = "]";
foreach ($attrParts as $part) {
$parts[] = $part;
}
$hasExpression = $hasExpression || $hasInterpolation;
return true;
}
$this->seek($s);
}
$this->seek($s);
return false;
}
// a space separated list of selectors
protected function tag(&$tag, $simple = false) {
if ($simple) {
$chars = '^@,:;{}\][>\(\) "\'';
} else {
$chars = '^@,;{}["\'';
}
$s = $this->seek();
$hasExpression = false;
$parts = array();
while ($this->tagBracket($parts, $hasExpression));
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
while (true) {
if ($this->matchReg('(['.$chars.'0-9]['.$chars.']*)', $m)) {
$parts[] = $m[1];
if ($simple) break;
while ($this->tagBracket($parts, $hasExpression));
continue;
}
if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
if ($this->interpolation($interp)) {
$hasExpression = true;
$interp[2] = true; // don't unescape
$parts[] = $interp;
continue;
}
if ($this->literal("@")) {
$parts[] = "@";
continue;
}
}
if ($this->unit($unit)) { // for keyframes
$parts[] = $unit[1];
$parts[] = $unit[2];
continue;
}
break;
}
$this->eatWhiteDefault = $oldWhite;
if (!$parts) {
$this->seek($s);
return false;
}
if ($hasExpression) {
$tag = array("exp", array("string", "", $parts));
} else {
$tag = trim(implode($parts));
}
$this->whitespace();
return true;
}
// a css function
protected function func(&$func) {
$s = $this->seek();
if ($this->matchReg('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
$fname = $m[1];
$sPreArgs = $this->seek();
$args = array();
while (true) {
$ss = $this->seek();
// this ugly nonsense is for ie filter properties
if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
$args[] = array("string", "", array($name, "=", $value));
} else {
$this->seek($ss);
if ($this->expressionList($value)) {
$args[] = $value;
}
}
if (!$this->literal(',')) break;
}
$args = array('list', ',', $args);
if ($this->literal(')')) {
$func = array('function', $fname, $args);
return true;
} elseif ($fname == 'url') {
// couldn't parse and in url? treat as string
$this->seek($sPreArgs);
if ($this->openString(")", $string) && $this->literal(")")) {
$func = array('function', $fname, $string);
return true;
}
}
}
$this->seek($s);
return false;
}
// consume a less variable
protected function variable(&$name) {
$s = $this->seek();
if ($this->literal($this->lessc->vPrefix, false) &&
($this->variable($sub) || $this->keyword($name))
) {
if (!empty($sub)) {
$name = array('variable', $sub);
} else {
$name = $this->lessc->vPrefix.$name;
}
return true;
}
$name = null;
$this->seek($s);
return false;
}
/**
* Consume an assignment operator
* Can optionally take a name that will be set to the current property name
*/
protected function assign($name = null) {
if ($name) $this->currentProperty = $name;
return $this->literal(':') || $this->literal('=');
}
// consume a keyword
protected function keyword(&$word) {
if ($this->matchReg('([\w_\-\*!"][\w\-_"]*)', $m)) {
$word = $m[1];
return true;
}
return false;
}
// consume an end of statement delimiter
protected function end() {
if ($this->literal(';', false)) {
return true;
} elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
// if there is end of file or a closing block next then we don't need a ;
return true;
}
return false;
}
protected function guards(&$guards) {
$s = $this->seek();
if (!$this->literal("when")) {
$this->seek($s);
return false;
}
$guards = array();
while ($this->guardGroup($g)) {
$guards[] = $g;
if (!$this->literal(",")) break;
}
if (count($guards) == 0) {
$guards = null;
$this->seek($s);
return false;
}
return true;
}
// a bunch of guards that are and'd together
// TODO rename to guardGroup
protected function guardGroup(&$guardGroup) {
$s = $this->seek();
$guardGroup = array();
while ($this->guard($guard)) {
$guardGroup[] = $guard;
if (!$this->literal("and")) break;
}
if (count($guardGroup) == 0) {
$guardGroup = null;
$this->seek($s);
return false;
}
return true;
}
protected function guard(&$guard) {
$s = $this->seek();
$negate = $this->literal("not");
if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
$guard = $exp;
if ($negate) $guard = array("negate", $guard);
return true;
}
$this->seek($s);
return false;
}
/* raw parsing functions */
protected function literal($what, $eatWhitespace = null) {
if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
// shortcut on single letter
if (!isset($what[1]) && isset($this->buffer[$this->count])) {
if ($this->buffer[$this->count] == $what) {
if (!$eatWhitespace) {
$this->count++;
return true;
}
// goes below...
} else {
return false;
}
}
if (!isset(self::$literalCache[$what])) {
self::$literalCache[$what] = lessc::preg_quote($what);
}
return $this->matchReg(self::$literalCache[$what], $m, $eatWhitespace);
}
protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
$s = $this->seek();
$items = array();
while ($this->$parseItem($value)) {
$items[] = $value;
if ($delim) {
if (!$this->literal($delim)) break;
}
}
if (count($items) == 0) {
$this->seek($s);
return false;
}
if ($flatten && count($items) == 1) {
$out = $items[0];
} else {
$out = array("list", $delim, $items);
}
return true;
}
// advance counter to next occurrence of $what
// $until - don't include $what in advance
// $allowNewline, if string, will be used as valid char set
protected function to($what, &$out, $until = false, $allowNewline = false) {
if (is_string($allowNewline)) {
$validChars = $allowNewline;
} else {
$validChars = $allowNewline ? "." : "[^\n]";
}
if (!$this->matchReg('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
if ($until) $this->count -= strlen($what); // give back $what
$out = $m[1];
return true;
}
// try to match something on head of buffer
protected function matchReg($regex, &$out, $eatWhitespace = null) {
if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
$r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
if (preg_match($r, $this->buffer, $out, 0, $this->count)) {
$this->count += strlen($out[0]);
if ($eatWhitespace && $this->writeComments) $this->whitespace();
return true;
}
return false;
}
// match some whitespace
protected function whitespace() {
if ($this->writeComments) {
$gotWhite = false;
while (preg_match(self::$whitePattern, $this->buffer, $m, 0, $this->count)) {
if (isset($m[1]) && empty($this->seenComments[$this->count])) {
$this->append(array("comment", $m[1]));
$this->seenComments[$this->count] = true;
}
$this->count += strlen($m[0]);
$gotWhite = true;
}
return $gotWhite;
} else {
$this->matchReg("", $m);
return strlen($m[0]) > 0;
}
}
// match something without consuming it
protected function peek($regex, &$out = null, $from=null) {
if (is_null($from)) $from = $this->count;
$r = '/'.$regex.'/Ais';
$result = preg_match($r, $this->buffer, $out, 0, $from);
return $result;
}
// seek to a spot in the buffer or return where we are on no argument
protected function seek($where = null) {
if ($where === null) return $this->count;
else $this->count = $where;
return true;
}
/* misc functions */
public function throwError($msg = "parse error", $count = null) {
$count = is_null($count) ? $this->count : $count;
$line = $this->line +
substr_count(substr($this->buffer, 0, $count), "\n");
if (!empty($this->sourceName)) {
$loc = "$this->sourceName on line $line";
} else {
$loc = "line: $line";
}
// TODO this depends on $this->count
if ($this->peek("(.*?)(\n|$)", $m, $count)) {
throw new exception("$msg: failed at `$m[1]` $loc");
} else {
throw new exception("$msg: $loc");
}
}
protected function pushBlock($selectors=null, $type=null) {
$b = new stdclass;
$b->parent = $this->env;
$b->type = $type;
$b->id = self::$nextBlockId++;
$b->isVararg = false; // TODO: kill me from here
$b->tags = $selectors;
$b->props = array();
$b->children = array();
$this->env = $b;
return $b;
}
// push a block that doesn't multiply tags
protected function pushSpecialBlock($type) {
return $this->pushBlock(null, $type);
}
// append a property to the current block
protected function append($prop, $pos = null) {
if ($pos !== null) $prop[-1] = $pos;
$this->env->props[] = $prop;
}
// pop something off the stack
protected function pop() {
$old = $this->env;
$this->env = $this->env->parent;
return $old;
}
// remove comments from $text
// todo: make it work for all functions, not just url
protected function removeComments($text) {
$look = array(
'url(', '//', '/*', '"', "'"
);
$out = '';
$min = null;
while (true) {
// find the next item
foreach ($look as $token) {
$pos = strpos($text, $token);
if ($pos !== false) {
if (!isset($min) || $pos < $min[1]) $min = array($token, $pos);
}
}
if (is_null($min)) break;
$count = $min[1];
$skip = 0;
$newlines = 0;
switch ($min[0]) {
case 'url(':
if (preg_match('/url\(.*?\)/', $text, $m, 0, $count))
$count += strlen($m[0]) - strlen($min[0]);
break;
case '"':
case "'":
if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count))
$count += strlen($m[0]) - 1;
break;
case '//':
$skip = strpos($text, "\n", $count);
if ($skip === false) $skip = strlen($text) - $count;
else $skip -= $count;
break;
case '/*':
if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
$skip = strlen($m[0]);
$newlines = substr_count($m[0], "\n");
}
break;
}
if ($skip == 0) $count += strlen($min[0]);
$out .= substr($text, 0, $count).str_repeat("\n", $newlines);
$text = substr($text, $count + $skip);
$min = null;
}
return $out.$text;
}
}
class lessc_formatter_classic {
public $indentChar = " ";
public $break = "\n";
public $open = " {";
public $close = "}";
public $selectorSeparator = ", ";
public $assignSeparator = ":";
public $openSingle = " { ";
public $closeSingle = " }";
public $disableSingle = false;
public $breakSelectors = false;
public $compressColors = false;
public function __construct() {
$this->indentLevel = 0;
}
public function indentStr($n = 0) {
return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
}
public function property($name, $value) {
return $name . $this->assignSeparator . $value . ";";
}
protected function isEmpty($block) {
if (empty($block->lines)) {
foreach ($block->children as $child) {
if (!$this->isEmpty($child)) return false;
}
return true;
}
return false;
}
public function block($block) {
if ($this->isEmpty($block)) return;
$inner = $pre = $this->indentStr();
$isSingle = !$this->disableSingle &&
is_null($block->type) && count($block->lines) == 1;
if (!empty($block->selectors)) {
$this->indentLevel++;
if ($this->breakSelectors) {
$selectorSeparator = $this->selectorSeparator . $this->break . $pre;
} else {
$selectorSeparator = $this->selectorSeparator;
}
echo $pre .
implode($selectorSeparator, $block->selectors);
if ($isSingle) {
echo $this->openSingle;
$inner = "";
} else {
echo $this->open . $this->break;
$inner = $this->indentStr();
}
}
if (!empty($block->lines)) {
$glue = $this->break.$inner;
echo $inner . implode($glue, $block->lines);
if (!$isSingle && !empty($block->children)) {
echo $this->break;
}
}
foreach ($block->children as $child) {
$this->block($child);
}
if (!empty($block->selectors)) {
if (!$isSingle && empty($block->children)) echo $this->break;
if ($isSingle) {
echo $this->closeSingle . $this->break;
} else {
echo $pre . $this->close . $this->break;
}
$this->indentLevel--;
}
}
}
class lessc_formatter_compressed extends lessc_formatter_classic {
public $disableSingle = true;
public $open = "{";
public $selectorSeparator = ",";
public $assignSeparator = ":";
public $break = "";
public $compressColors = true;
public function indentStr($n = 0) {
return "";
}
}
class lessc_formatter_lessjs extends lessc_formatter_classic {
public $disableSingle = true;
public $breakSelectors = true;
public $assignSeparator = ": ";
public $selectorSeparator = ",";
}