diff --git a/Library/Org/Crypt.php b/Library/Org/Crypt.php deleted file mode 100644 index 77adcf88..00000000 --- a/Library/Org/Crypt.php +++ /dev/null @@ -1,74 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org; - -class Crypt { - /** - * 加密字符串 - * @access public - * @param string $str 字符串 - * @param string $key 加密key - * @return string - */ - static public function encrypt($data,$key,$expire=0){ - $key = md5($key); - $data = base64_encode($data); - $x = 0; - $len = strlen($data); - $l = strlen($key); - $char = ''; - for ($i = 0; $i< $len; $i++) { - if ($x == $l) $x = 0; - $char .=substr($key, $x, 1); - $x++; - } - $str = sprintf('%010d', $expire ? $expire + time() : 0); - for ($i=0; $i< $len; $i++) { - $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256); - } - return str_replace('=', '', base64_encode($str)); - } - - /** - * 解密字符串 - * @access public - * @param string $str 字符串 - * @param string $key 加密key - * @return string - */ - static public function decrypt($data,$key){ - $key = md5($key); - $x = 0; - $data = base64_decode($data); - $expire = substr($data,0,10); - $data = substr($data,10); - if($expire > 0 && $expire -// +---------------------------------------------------------------------- - -namespace Org; - -/* 缩略图相关常量定义 */ -define('THINKIMAGE_THUMB_SCALING', 1); //常量,标识缩略图等比例缩放类型 -define('THINKIMAGE_THUMB_FILLED', 2); //常量,标识缩略图缩放后填充类型 -define('THINKIMAGE_THUMB_CENTER', 3); //常量,标识缩略图居中裁剪类型 -define('THINKIMAGE_THUMB_NORTHWEST', 4); //常量,标识缩略图左上角裁剪类型 -define('THINKIMAGE_THUMB_SOUTHEAST', 5); //常量,标识缩略图右下角裁剪类型 -define('THINKIMAGE_THUMB_FIXED', 6); //常量,标识缩略图固定尺寸缩放类型 - -/* 水印相关常量定义 */ -define('THINKIMAGE_WATER_NORTHWEST', 1); //常量,标识左上角水印 -define('THINKIMAGE_WATER_NORTH', 2); //常量,标识上居中水印 -define('THINKIMAGE_WATER_NORTHEAST', 3); //常量,标识右上角水印 -define('THINKIMAGE_WATER_WEST', 4); //常量,标识左居中水印 -define('THINKIMAGE_WATER_CENTER', 5); //常量,标识居中水印 -define('THINKIMAGE_WATER_EAST', 6); //常量,标识右居中水印 -define('THINKIMAGE_WATER_SOUTHWEST', 7); //常量,标识左下角水印 -define('THINKIMAGE_WATER_SOUTH', 8); //常量,标识下居中水印 -define('THINKIMAGE_WATER_SOUTHEAST', 9); //常量,标识右下角水印 - -/** - * 图片处理驱动类,可配置图片处理库 - * 目前支持GD库和imagick - * @author 麦当苗儿 - */ -class Image { - /** - * 图片资源 - * @var resource - */ - private static $im; - - /** - * 构造方法,用于实例化一个图片处理对象 - * @param string $type 要使用的类库,默认使用GD库 - */ - public function init($type = 'Gd', $imgname = null){ - /* 引入处理库,实例化图片处理对象 */ - $class = '\\Org\\Image\\Driver\\'.ucwords($type); - self::$im = new $class($imgname); - return self::$im; - } - - // 调用驱动类的方法 - static public function __callStatic($method, $params){ - if(empty(self::$im)) { - self::init(); - } - return call_user_func_array(array(self::$im, $method), $params); - } - -} \ No newline at end of file diff --git a/Library/Org/Image/Driver/Gd.php b/Library/Org/Image/Driver/Gd.php deleted file mode 100644 index 6e620e9a..00000000 --- a/Library/Org/Image/Driver/Gd.php +++ /dev/null @@ -1,549 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Image\Driver; - -class Gd{ - /** - * 图像资源对象 - * @var resource - */ - private $im; - private $gif; - /** - * 图像信息,包括width,height,type,mime,size - * @var array - */ - private $info; - - /** - * 构造方法,可用于打开一张图像 - * @param string $imgname 图像路径 - */ - public function __construct($imgname = null) { - $imgname && $this->open($imgname); - } - - /** - * 打开一张图像 - * @param string $imgname 图像路径 - */ - public function open($imgname){ - //检测图像文件 - if(!is_file($imgname)) throw new Exception('不存在的图像文件'); - - //获取图像信息 - $info = getimagesize($imgname); - - //检测图像合法性 - if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){ - throw new Exception('非法图像文件'); - } - - //设置图像信息 - $this->info = [ - 'width' => $info[0], - 'height' => $info[1], - 'type' => image_type_to_extension($info[2], false), - 'mime' => $info['mime'], - ]; - - //销毁已存在的图像 - empty($this->im) || imagedestroy($this->im); - - //打开图像 - if('gif' == $this->info['type']){ - $class = '\Org\Image\Driver\Gif'; - $this->gif = new $class($imgname); - $this->im = imagecreatefromstring($this->gif->image()); - } else { - $fun = "imagecreatefrom{$this->info['type']}"; - $this->im = $fun($imgname); - } - return $this; - } - - /** - * 保存图像 - * @param string $imgname 图像保存名称 - * @param string $type 图像类型 - * @param boolean $interlace 是否对JPEG类型图像设置隔行扫描 - */ - public function save($imgname, $type = null, $interlace = true){ - if(empty($this->im)) throw new \Exception('没有可以被保存的图像资源'); - - //自动获取图像类型 - if(is_null($type)){ - $type = $this->info['type']; - } else { - $type = strtolower($type); - } - - //JPEG图像设置隔行扫描 - if('jpeg' == $type || 'jpg' == $type){ - $type = 'jpeg'; - imageinterlace($this->im, $interlace); - } - - //保存图像 - if('gif' == $type && !empty($this->gif)){ - $this->gif->save($imgname); - } else { - $fun = "image{$type}"; - $fun($this->im, $imgname); - } - return $this; - } - - /** - * 返回图像宽度 - * @return integer 图像宽度 - */ - public function width(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['width']; - } - - /** - * 返回图像高度 - * @return integer 图像高度 - */ - public function height(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['height']; - } - - /** - * 返回图像类型 - * @return string 图像类型 - */ - public function type(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['type']; - } - - /** - * 返回图像MIME类型 - * @return string 图像MIME类型 - */ - public function mime(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['mime']; - } - - /** - * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度 - * @return array 图像尺寸 - */ - public function size(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return [$this->info['width'], $this->info['height']]; - } - - /** - * 裁剪图像 - * @param integer $w 裁剪区域宽度 - * @param integer $h 裁剪区域高度 - * @param integer $x 裁剪区域x坐标 - * @param integer $y 裁剪区域y坐标 - * @param integer $width 图像保存宽度 - * @param integer $height 图像保存高度 - */ - public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){ - if(empty($this->im)) throw new Exception('没有可以被裁剪的图像资源'); - - //设置保存尺寸 - empty($width) && $width = $w; - empty($height) && $height = $h; - - do { - //创建新图像 - $img = imagecreatetruecolor($width, $height); - // 调整默认颜色 - $color = imagecolorallocate($img, 255, 255, 255); - imagefill($img, 0, 0, $color); - - //裁剪 - imagecopyresampled($img, $this->im, 0, 0, $x, $y, $width, $height, $w, $h); - imagedestroy($this->im); //销毁原图 - - //设置新图像 - $this->im = $img; - } while(!empty($this->gif) && $this->gifNext()); - - $this->info['width'] = $width; - $this->info['height'] = $height; - return $this; - } - - /** - * 生成缩略图 - * @param integer $width 缩略图最大宽度 - * @param integer $height 缩略图最大高度 - * @param integer $type 缩略图裁剪类型 - */ - public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){ - if(empty($this->im)) throw new Exception('没有可以被缩略的图像资源'); - - //原图宽度和高度 - $w = $this->info['width']; - $h = $this->info['height']; - - /* 计算缩略图生成的必要参数 */ - switch ($type) { - /* 等比例缩放 */ - case THINKIMAGE_THUMB_SCALING: - //原图尺寸小于缩略图尺寸则不进行缩略 - if($w < $width && $h < $height) return; - - //计算缩放比例 - $scale = min($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $x = $y = 0; - $width = $w * $scale; - $height = $h * $scale; - break; - - /* 居中裁剪 */ - case THINKIMAGE_THUMB_CENTER: - //计算缩放比例 - $scale = max($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $w = $width/$scale; - $h = $height/$scale; - $x = ($this->info['width'] - $w)/2; - $y = ($this->info['height'] - $h)/2; - break; - - /* 左上角裁剪 */ - case THINKIMAGE_THUMB_NORTHWEST: - //计算缩放比例 - $scale = max($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $x = $y = 0; - $w = $width/$scale; - $h = $height/$scale; - break; - - /* 右下角裁剪 */ - case THINKIMAGE_THUMB_SOUTHEAST: - //计算缩放比例 - $scale = max($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $w = $width/$scale; - $h = $height/$scale; - $x = $this->info['width'] - $w; - $y = $this->info['height'] - $h; - break; - - /* 填充 */ - case THINKIMAGE_THUMB_FILLED: - //计算缩放比例 - if($w < $width && $h < $height){ - $scale = 1; - } else { - $scale = min($width/$w, $height/$h); - } - - //设置缩略图的坐标及宽度和高度 - $neww = $w * $scale; - $newh = $h * $scale; - $posx = ($width - $w * $scale)/2; - $posy = ($height - $h * $scale)/2; - - do{ - //创建新图像 - $img = imagecreatetruecolor($width, $height); - // 调整默认颜色 - $color = imagecolorallocate($img, 255, 255, 255); - imagefill($img, 0, 0, $color); - - //裁剪 - imagecopyresampled($img, $this->im, $posx, $posy, $x, $y, $neww, $newh, $w, $h); - imagedestroy($this->im); //销毁原图 - $this->im = $img; - } while(!empty($this->gif) && $this->gifNext()); - - $this->info['width'] = $width; - $this->info['height'] = $height; - return; - - /* 固定 */ - case THINKIMAGE_THUMB_FIXED: - $x = $y = 0; - break; - - default: - throw new Exception('不支持的缩略图裁剪类型'); - } - - /* 裁剪图像 */ - $this->crop($w, $h, $x, $y, $width, $height); - return $this; - } - - /** - * 添加水印 - * @param string $source 水印图片路径 - * @param integer $locate 水印位置 - * @param integer $alpha 水印透明度 - */ - public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){ - //资源检测 - if(empty($this->im)) throw new Exception('没有可以被添加水印的图像资源'); - if(!is_file($source)) throw new Exception('水印图像不存在'); - - //获取水印图像信息 - $info = getimagesize($source); - if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){ - throw new Exception('非法水印文件'); - } - - //创建水印图像资源 - $fun = 'imagecreatefrom' . image_type_to_extension($info[2], false); - $water = $fun($source); - - //设定水印图像的混色模式 - imagealphablending($water, true); - - /* 设定水印位置 */ - switch ($locate) { - /* 右下角水印 */ - case THINKIMAGE_WATER_SOUTHEAST: - $x = $this->info['width'] - $info[0]; - $y = $this->info['height'] - $info[1]; - break; - - /* 左下角水印 */ - case THINKIMAGE_WATER_SOUTHWEST: - $x = 0; - $y = $this->info['height'] - $info[1]; - break; - - /* 左上角水印 */ - case THINKIMAGE_WATER_NORTHWEST: - $x = $y = 0; - break; - - /* 右上角水印 */ - case THINKIMAGE_WATER_NORTHEAST: - $x = $this->info['width'] - $info[0]; - $y = 0; - break; - - /* 居中水印 */ - case THINKIMAGE_WATER_CENTER: - $x = ($this->info['width'] - $info[0])/2; - $y = ($this->info['height'] - $info[1])/2; - break; - - /* 下居中水印 */ - case THINKIMAGE_WATER_SOUTH: - $x = ($this->info['width'] - $info[0])/2; - $y = $this->info['height'] - $info[1]; - break; - - /* 右居中水印 */ - case THINKIMAGE_WATER_EAST: - $x = $this->info['width'] - $info[0]; - $y = ($this->info['height'] - $info[1])/2; - break; - - /* 上居中水印 */ - case THINKIMAGE_WATER_NORTH: - $x = ($this->info['width'] - $info[0])/2; - $y = 0; - break; - - /* 左居中水印 */ - case THINKIMAGE_WATER_WEST: - $x = 0; - $y = ($this->info['height'] - $info[1])/2; - break; - - default: - /* 自定义水印坐标 */ - if(is_array($locate)){ - list($x, $y) = $locate; - } else { - throw new Exception('不支持的水印位置类型'); - } - } - - do{ - //添加水印 - $src = imagecreatetruecolor($info[0], $info[1]); - // 调整默认颜色 - $color = imagecolorallocate($src, 255, 255, 255); - imagefill($src, 0, 0, $color); - - imagecopy($src, $this->im, 0, 0, $x, $y, $info[0], $info[1]); - imagecopy($src, $water, 0, 0, 0, 0, $info[0], $info[1]); - imagecopymerge($this->im, $src, $x, $y, 0, 0, $info[0], $info[1], 100); - - //销毁零时图片资源 - imagedestroy($src); - } while(!empty($this->gif) && $this->gifNext()); - - //销毁水印资源 - imagedestroy($water); - return $this; - } - - /** - * 图像添加文字 - * @param string $text 添加的文字 - * @param string $font 字体路径 - * @param integer $size 字号 - * @param string $color 文字颜色 - * @param integer $locate 文字写入位置 - * @param integer $offset 文字相对当前位置的偏移量 - * @param integer $angle 文字倾斜角度 - */ - public function text($text, $font, $size, $color = '#00000000', - $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){ - //资源检测 - if(empty($this->im)) throw new Exception('没有可以被写入文字的图像资源'); - if(!is_file($font)) throw new Exception("不存在的字体文件:{$font}"); - - //获取文字信息 - $info = imagettfbbox($size, $angle, $font, $text); - $minx = min($info[0], $info[2], $info[4], $info[6]); - $maxx = max($info[0], $info[2], $info[4], $info[6]); - $miny = min($info[1], $info[3], $info[5], $info[7]); - $maxy = max($info[1], $info[3], $info[5], $info[7]); - - /* 计算文字初始坐标和尺寸 */ - $x = $minx; - $y = abs($miny); - $w = $maxx - $minx; - $h = $maxy - $miny; - - /* 设定文字位置 */ - switch ($locate) { - /* 右下角文字 */ - case THINKIMAGE_WATER_SOUTHEAST: - $x += $this->info['width'] - $w; - $y += $this->info['height'] - $h; - break; - - /* 左下角文字 */ - case THINKIMAGE_WATER_SOUTHWEST: - $y += $this->info['height'] - $h; - break; - - /* 左上角文字 */ - case THINKIMAGE_WATER_NORTHWEST: - // 起始坐标即为左上角坐标,无需调整 - break; - - /* 右上角文字 */ - case THINKIMAGE_WATER_NORTHEAST: - $x += $this->info['width'] - $w; - break; - - /* 居中文字 */ - case THINKIMAGE_WATER_CENTER: - $x += ($this->info['width'] - $w)/2; - $y += ($this->info['height'] - $h)/2; - break; - - /* 下居中文字 */ - case THINKIMAGE_WATER_SOUTH: - $x += ($this->info['width'] - $w)/2; - $y += $this->info['height'] - $h; - break; - - /* 右居中文字 */ - case THINKIMAGE_WATER_EAST: - $x += $this->info['width'] - $w; - $y += ($this->info['height'] - $h)/2; - break; - - /* 上居中文字 */ - case THINKIMAGE_WATER_NORTH: - $x += ($this->info['width'] - $w)/2; - break; - - /* 左居中文字 */ - case THINKIMAGE_WATER_WEST: - $y += ($this->info['height'] - $h)/2; - break; - - default: - /* 自定义文字坐标 */ - if(is_array($locate)){ - list($posx, $posy) = $locate; - $x += $posx; - $y += $posy; - } else { - throw new Exception('不支持的文字位置类型'); - } - } - - /* 设置偏移量 */ - if(is_array($offset)){ - $offset = array_map('intval', $offset); - list($ox, $oy) = $offset; - } else{ - $offset = intval($offset); - $ox = $oy = $offset; - } - - /* 设置颜色 */ - if(is_string($color) && 0 === strpos($color, '#')){ - $color = str_split(substr($color, 1), 2); - $color = array_map('hexdec', $color); - if(empty($color[3]) || $color[3] > 127){ - $color[3] = 0; - } - } elseif (!is_array($color)) { - throw new Exception('错误的颜色值'); - } - - do{ - /* 写入文字 */ - $col = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $color[3]); - imagettftext($this->im, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text); - } while(!empty($this->gif) && $this->gifNext()); - return $this; - } - - /* 切换到GIF的下一帧并保存当前帧,内部使用 */ - private function gifNext(){ - ob_start(); - ob_implicit_flush(0); - imagegif($this->im); - $img = ob_get_clean(); - - $this->gif->image($img); - $next = $this->gif->nextImage(); - - if($next){ - $this->im = imagecreatefromstring($next); - return $next; - } else { - $this->im = imagecreatefromstring($this->gif->image()); - return false; - } - } - - /** - * 析构方法,用于销毁图像资源 - */ - public function __destruct() { - empty($this->im) || imagedestroy($this->im); - } -} \ No newline at end of file diff --git a/Library/Org/Image/Driver/Gif.php b/Library/Org/Image/Driver/Gif.php deleted file mode 100644 index 67c7894f..00000000 --- a/Library/Org/Image/Driver/Gif.php +++ /dev/null @@ -1,570 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Image\Driver; - -class Gif{ - /** - * GIF帧列表 - * @var array - */ - private $frames = []; - - /** - * 每帧等待时间列表 - * @var array - */ - private $delays = []; - - /** - * 构造方法,用于解码GIF图片 - * @param string $src GIF图片数据 - * @param string $mod 图片数据类型 - */ - public function __construct($src = null, $mod = 'url') { - if(!is_null($src)){ - if('url' == $mod && is_file($src)){ - $src = file_get_contents($src); - } - - /* 解码GIF图片 */ - try{ - $de = new GIFDecoder($src); - $this->frames = $de->GIFGetFrames(); - $this->delays = $de->GIFGetDelays(); - } catch(Exception $e){ - throw new Exception("解码GIF图片出错"); - } - } - } - - /** - * 设置或获取当前帧的数据 - * @param string $stream 二进制数据流 - * @return boolean 获取到的数据 - */ - public function image($stream = null){ - if(is_null($stream)){ - $current = current($this->frames); - return false === $current ? reset($this->frames) : $current; - } else { - $this->frames[key($this->frames)] = $stream; - } - } - - /** - * 将当前帧移动到下一帧 - * @return string 当前帧数据 - */ - public function nextImage(){ - return next($this->frames); - } - - /** - * 编码并保存当前GIF图片 - * @param string $gifname 图片名称 - */ - public function save($gifname){ - $gif = new GIFEncoder($this->frames, $this->delays, 0, 2, 0, 0, 0, 'bin'); - file_put_contents($gifname, $gif->GetAnimation()); - } - -} - - -/* -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:: -:: GIFEncoder Version 2.0 by László Zsidi, http://gifs.hu -:: -:: This class is a rewritten 'GifMerge.class.php' version. -:: -:: Modification: -:: - Simplified and easy code, -:: - Ultra fast encoding, -:: - Built-in errors, -:: - Stable working -:: -:: -:: Updated at 2007. 02. 13. '00.05.AM' -:: -:: -:: -:: Try on-line GIFBuilder Form demo based on GIFEncoder. -:: -:: http://gifs.hu/phpclasses/demos/GifBuilder/ -:: -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -*/ - -Class GIFEncoder { - var $GIF = "GIF89a"; /* GIF header 6 bytes */ - var $VER = "GIFEncoder V2.05"; /* Encoder version */ - - var $BUF = Array ( ); - var $LOP = 0; - var $DIS = 2; - var $COL = -1; - var $IMG = -1; - - var $ERR = Array ( - 'ERR00'=>"Does not supported function for only one image!", - 'ERR01'=>"Source is not a GIF image!", - 'ERR02'=>"Unintelligible flag ", - 'ERR03'=>"Does not make animation from animated GIF source", - ); - - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFEncoder... - :: - */ - function GIFEncoder ( - $GIF_src, $GIF_dly, $GIF_lop, $GIF_dis, - $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod - ) { - if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_tim ) ) { - printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] ); - exit ( 0 ); - } - $this->LOP = ( $GIF_lop > -1 ) ? $GIF_lop : 0; - $this->DIS = ( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2; - $this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ? - ( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1; - - for ( $i = 0; $i < count ( $GIF_src ); $i++ ) { - if ( strToLower ( $GIF_mod ) == "url" ) { - $this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) ); - } - else if ( strToLower ( $GIF_mod ) == "bin" ) { - $this->BUF [ ] = $GIF_src [ $i ]; - } - else { - printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod ); - exit ( 0 ); - } - if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) { - printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] ); - exit ( 0 ); - } - for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = TRUE; $k; $j++ ) { - switch ( $this->BUF [ $i ] { $j } ) { - case "!": - if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) { - printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) ); - exit ( 0 ); - } - break; - case ";": - $k = FALSE; - break; - } - } - } - GIFEncoder::GIFAddHeader ( ); - for ( $i = 0; $i < count ( $this->BUF ); $i++ ) { - GIFEncoder::GIFAddFrames ( $i, $GIF_dly [ $i ] ); - } - GIFEncoder::GIFAddFooter ( ); - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFAddHeader... - :: - */ - function GIFAddHeader ( ) { - $cmap = 0; - - if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) { - $cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ); - - $this->GIF .= substr ( $this->BUF [ 0 ], 6, 7 ); - $this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap ); - $this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFEncoder::GIFWord ( $this->LOP ) . "\0"; - } - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFAddFrames... - :: - */ - function GIFAddFrames ( $i, $d ) { - - $Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); - - $Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1; - $Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end ); - - $Global_len = 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); - $Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); - - $Global_rgb = substr ( $this->BUF [ 0 ], 13, - 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ) ); - $Locals_rgb = substr ( $this->BUF [ $i ], 13, - 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ); - - $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 0 ) . - chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0"; - - if ( $this->COL > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) { - for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) { - if ( - ord ( $Locals_rgb { 3 * $j + 0 } ) == ( ( $this->COL >> 16 ) & 0xFF ) && - ord ( $Locals_rgb { 3 * $j + 1 } ) == ( ( $this->COL >> 8 ) & 0xFF ) && - ord ( $Locals_rgb { 3 * $j + 2 } ) == ( ( $this->COL >> 0 ) & 0xFF ) - ) { - $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 1 ) . - chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . chr ( $j ) . "\x0"; - break; - } - } - } - switch ( $Locals_tmp { 0 } ) { - case "!": - $Locals_img = substr ( $Locals_tmp, 8, 10 ); - $Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 ); - break; - case ",": - $Locals_img = substr ( $Locals_tmp, 0, 10 ); - $Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 ); - break; - } - if ( ord ( $this->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) { - if ( $Global_len == $Locals_len ) { - if ( GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len ) ) { - $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); - } - else { - $byte = ord ( $Locals_img { 9 } ); - $byte |= 0x80; - $byte &= 0xF8; - $byte |= ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); - $Locals_img { 9 } = chr ( $byte ); - $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); - } - } - else { - $byte = ord ( $Locals_img { 9 } ); - $byte |= 0x80; - $byte &= 0xF8; - $byte |= ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); - $Locals_img { 9 } = chr ( $byte ); - $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); - } - } - else { - $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); - } - $this->IMG = 1; - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFAddFooter... - :: - */ - function GIFAddFooter ( ) { - $this->GIF .= ";"; - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFBlockCompare... - :: - */ - function GIFBlockCompare ( $GlobalBlock, $LocalBlock, $Len ) { - - for ( $i = 0; $i < $Len; $i++ ) { - if ( - $GlobalBlock { 3 * $i + 0 } != $LocalBlock { 3 * $i + 0 } || - $GlobalBlock { 3 * $i + 1 } != $LocalBlock { 3 * $i + 1 } || - $GlobalBlock { 3 * $i + 2 } != $LocalBlock { 3 * $i + 2 } - ) { - return ( 0 ); - } - } - - return ( 1 ); - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFWord... - :: - */ - function GIFWord ( $int ) { - - return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) ); - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GetAnimation... - :: - */ - function GetAnimation ( ) { - return ( $this->GIF ); - } -} - - -/* -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:: -:: GIFDecoder Version 2.0 by László Zsidi, http://gifs.hu -:: -:: Created at 2007. 02. 01. '07.47.AM' -:: -:: -:: -:: -:: Try on-line GIFBuilder Form demo based on GIFDecoder. -:: -:: http://gifs.hu/phpclasses/demos/GifBuilder/ -:: -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -*/ - -Class GIFDecoder { - var $GIF_buffer = Array ( ); - var $GIF_arrays = Array ( ); - var $GIF_delays = Array ( ); - var $GIF_stream = ""; - var $GIF_string = ""; - var $GIF_bfseek = 0; - - var $GIF_screen = Array ( ); - var $GIF_global = Array ( ); - var $GIF_sorted; - var $GIF_colorS; - var $GIF_colorC; - var $GIF_colorF; - - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFDecoder ( $GIF_pointer ) - :: - */ - function GIFDecoder ( $GIF_pointer ) { - $this->GIF_stream = $GIF_pointer; - - GIFDecoder::GIFGetByte ( 6 ); // GIF89a - GIFDecoder::GIFGetByte ( 7 ); // Logical Screen Descriptor - - $this->GIF_screen = $this->GIF_buffer; - $this->GIF_colorF = $this->GIF_buffer [ 4 ] & 0x80 ? 1 : 0; - $this->GIF_sorted = $this->GIF_buffer [ 4 ] & 0x08 ? 1 : 0; - $this->GIF_colorC = $this->GIF_buffer [ 4 ] & 0x07; - $this->GIF_colorS = 2 << $this->GIF_colorC; - - if ( $this->GIF_colorF == 1 ) { - GIFDecoder::GIFGetByte ( 3 * $this->GIF_colorS ); - $this->GIF_global = $this->GIF_buffer; - } - /* - * - * 05.06.2007. - * Made a little modification - * - * - - for ( $cycle = 1; $cycle; ) { - + if ( GIFDecoder::GIFGetByte ( 1 ) ) { - - switch ( $this->GIF_buffer [ 0 ] ) { - - case 0x21: - - GIFDecoder::GIFReadExtensions ( ); - - break; - - case 0x2C: - - GIFDecoder::GIFReadDescriptor ( ); - - break; - - case 0x3B: - - $cycle = 0; - - break; - - } - - } - + else { - + $cycle = 0; - + } - - } - */ - for ( $cycle = 1; $cycle; ) { - if ( GIFDecoder::GIFGetByte ( 1 ) ) { - switch ( $this->GIF_buffer [ 0 ] ) { - case 0x21: - GIFDecoder::GIFReadExtensions ( ); - break; - case 0x2C: - GIFDecoder::GIFReadDescriptor ( ); - break; - case 0x3B: - $cycle = 0; - break; - } - } - else { - $cycle = 0; - } - } - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFReadExtension ( ) - :: - */ - function GIFReadExtensions ( ) { - GIFDecoder::GIFGetByte ( 1 ); - for ( ; ; ) { - GIFDecoder::GIFGetByte ( 1 ); - if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { - break; - } - GIFDecoder::GIFGetByte ( $u ); - /* - * 07.05.2007. - * Implemented a new line for a new function - * to determine the originaly delays between - * frames. - * - */ - if ( $u == 4 ) { - $this->GIF_delays [ ] = ( $this->GIF_buffer [ 1 ] | $this->GIF_buffer [ 2 ] << 8 ); - } - } - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFReadExtension ( ) - :: - */ - function GIFReadDescriptor ( ) { - $GIF_screen = Array ( ); - - GIFDecoder::GIFGetByte ( 9 ); - $GIF_screen = $this->GIF_buffer; - $GIF_colorF = $this->GIF_buffer [ 8 ] & 0x80 ? 1 : 0; - if ( $GIF_colorF ) { - $GIF_code = $this->GIF_buffer [ 8 ] & 0x07; - $GIF_sort = $this->GIF_buffer [ 8 ] & 0x20 ? 1 : 0; - } - else { - $GIF_code = $this->GIF_colorC; - $GIF_sort = $this->GIF_sorted; - } - $GIF_size = 2 << $GIF_code; - $this->GIF_screen [ 4 ] &= 0x70; - $this->GIF_screen [ 4 ] |= 0x80; - $this->GIF_screen [ 4 ] |= $GIF_code; - if ( $GIF_sort ) { - $this->GIF_screen [ 4 ] |= 0x08; - } - $this->GIF_string = "GIF87a"; - GIFDecoder::GIFPutByte ( $this->GIF_screen ); - if ( $GIF_colorF == 1 ) { - GIFDecoder::GIFGetByte ( 3 * $GIF_size ); - GIFDecoder::GIFPutByte ( $this->GIF_buffer ); - } - else { - GIFDecoder::GIFPutByte ( $this->GIF_global ); - } - $this->GIF_string .= chr ( 0x2C ); - $GIF_screen [ 8 ] &= 0x40; - GIFDecoder::GIFPutByte ( $GIF_screen ); - GIFDecoder::GIFGetByte ( 1 ); - GIFDecoder::GIFPutByte ( $this->GIF_buffer ); - for ( ; ; ) { - GIFDecoder::GIFGetByte ( 1 ); - GIFDecoder::GIFPutByte ( $this->GIF_buffer ); - if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { - break; - } - GIFDecoder::GIFGetByte ( $u ); - GIFDecoder::GIFPutByte ( $this->GIF_buffer ); - } - $this->GIF_string .= chr ( 0x3B ); - /* - Add frames into $GIF_stream array... - */ - $this->GIF_arrays [ ] = $this->GIF_string; - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFGetByte ( $len ) - :: - */ - - /* - * - * 05.06.2007. - * Made a little modification - * - * - - function GIFGetByte ( $len ) { - - $this->GIF_buffer = Array ( ); - - - - for ( $i = 0; $i < $len; $i++ ) { - + if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) { - + return 0; - + } - - $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); - - } - + return 1; - - } - */ - function GIFGetByte ( $len ) { - $this->GIF_buffer = Array ( ); - - for ( $i = 0; $i < $len; $i++ ) { - if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) { - return 0; - } - $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); - } - return 1; - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFPutByte ( $bytes ) - :: - */ - function GIFPutByte ( $bytes ) { - for ( $i = 0; $i < count ( $bytes ); $i++ ) { - $this->GIF_string .= chr ( $bytes [ $i ] ); - } - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: PUBLIC FUNCTIONS - :: - :: - :: GIFGetFrames ( ) - :: - */ - function GIFGetFrames ( ) { - return ( $this->GIF_arrays ); - } - /* - ::::::::::::::::::::::::::::::::::::::::::::::::::: - :: - :: GIFGetDelays ( ) - :: - */ - function GIFGetDelays ( ) { - return ( $this->GIF_delays ); - } -} diff --git a/Library/Org/Image/Driver/Imagick.php b/Library/Org/Image/Driver/Imagick.php deleted file mode 100644 index 845091bd..00000000 --- a/Library/Org/Image/Driver/Imagick.php +++ /dev/null @@ -1,591 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Image\Driver; - -class Imagick{ - /** - * 图像资源对象 - * @var resource - */ - private $im; - - /** - * 图像信息,包括width,height,type,mime,size - * @var array - */ - private $info; - - /** - * 构造方法,可用于打开一张图像 - * @param string $imgname 图像路径 - */ - public function __construct($imgname = null) { - if ( !extension_loaded('Imagick') ) { - E(L('_NOT_SUPPERT_').':Imagick'); - } - $imgname && $this->open($imgname); - } - - /** - * 打开一张图像 - * @param string $imgname 图像路径 - */ - public function open($imgname){ - //检测图像文件 - if(!is_file($imgname)) throw new Exception('不存在的图像文件'); - - //销毁已存在的图像 - empty($this->im) || $this->im->destroy(); - - //载入图像 - $this->im = new \Imagick(realpath($imgname)); - - //设置图像信息 - $this->info = [ - 'width' => $this->im->getImageWidth(), - 'height' => $this->im->getImageHeight(), - 'type' => strtolower($this->im->getImageFormat()), - 'mime' => $this->im->getImageMimeType(), - ]; - } - - /** - * 保存图像 - * @param string $imgname 图像保存名称 - * @param string $type 图像类型 - * @param boolean $interlace 是否对JPEG类型图像设置隔行扫描 - */ - public function save($imgname, $type = null, $interlace = true){ - if(empty($this->im)) throw new Exception('没有可以被保存的图像资源'); - - //设置图片类型 - if(is_null($type)){ - $type = $this->info['type']; - } else { - $type = strtolower($type); - $this->im->setImageFormat($type); - } - - //JPEG图像设置隔行扫描 - if('jpeg' == $type || 'jpg' == $type){ - $this->im->setImageInterlaceScheme(1); - } - - //去除图像配置信息 - $this->im->stripImage(); - - //保存图像 - $imgname = realpath(dirname($imgname)) . '/' . basename($imgname); //强制绝对路径 - if ('gif' == $type) { - $this->im->writeImages($imgname, true); - } else { - $this->im->writeImage($imgname); - } - } - - /** - * 返回图像宽度 - * @return integer 图像宽度 - */ - public function width(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['width']; - } - - /** - * 返回图像高度 - * @return integer 图像高度 - */ - public function height(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['height']; - } - - /** - * 返回图像类型 - * @return string 图像类型 - */ - public function type(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['type']; - } - - /** - * 返回图像MIME类型 - * @return string 图像MIME类型 - */ - public function mime(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return $this->info['mime']; - } - - /** - * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度 - * @return array 图像尺寸 - */ - public function size(){ - if(empty($this->im)) throw new Exception('没有指定图像资源'); - return [$this->info['width'], $this->info['height']]; - } - - /** - * 裁剪图像 - * @param integer $w 裁剪区域宽度 - * @param integer $h 裁剪区域高度 - * @param integer $x 裁剪区域x坐标 - * @param integer $y 裁剪区域y坐标 - * @param integer $width 图像保存宽度 - * @param integer $height 图像保存高度 - */ - public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){ - if(empty($this->im)) throw new Exception('没有可以被裁剪的图像资源'); - - //设置保存尺寸 - empty($width) && $width = $w; - empty($height) && $height = $h; - - //裁剪图片 - if('gif' == $this->info['type']){ - $img = $this->im->coalesceImages(); - $this->im->destroy(); //销毁原图 - - //循环裁剪每一帧 - do { - $this->_crop($w, $h, $x, $y, $width, $height, $img); - } while ($img->nextImage()); - - //压缩图片 - $this->im = $img->deconstructImages(); - $img->destroy(); //销毁零时图片 - } else { - $this->_crop($w, $h, $x, $y, $width, $height); - } - } - - /* 裁剪图片,内部调用 */ - private function _crop($w, $h, $x, $y, $width, $height, $img = null){ - is_null($img) && $img = $this->im; - - //裁剪 - $info = $this->info; - if($x != 0 || $y != 0 || $w != $info['width'] || $h != $info['height']){ - $img->cropImage($w, $h, $x, $y); - $img->setImagePage($w, $h, 0, 0); //调整画布和图片一致 - } - - //调整大小 - if($w != $width || $h != $height){ - $img->sampleImage($width, $height); - } - - //设置缓存尺寸 - $this->info['width'] = $w; - $this->info['height'] = $h; - } - - /** - * 生成缩略图 - * @param integer $width 缩略图最大宽度 - * @param integer $height 缩略图最大高度 - * @param integer $type 缩略图裁剪类型 - */ - public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){ - if(empty($this->im)) throw new Exception('没有可以被缩略的图像资源'); - - //原图宽度和高度 - $w = $this->info['width']; - $h = $this->info['height']; - - /* 计算缩略图生成的必要参数 */ - switch ($type) { - /* 等比例缩放 */ - case THINKIMAGE_THUMB_SCALING: - //原图尺寸小于缩略图尺寸则不进行缩略 - if($w < $width && $h < $height) return; - - //计算缩放比例 - $scale = min($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $x = $y = 0; - $width = $w * $scale; - $height = $h * $scale; - break; - - /* 居中裁剪 */ - case THINKIMAGE_THUMB_CENTER: - //计算缩放比例 - $scale = max($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $w = $width/$scale; - $h = $height/$scale; - $x = ($this->info['width'] - $w)/2; - $y = ($this->info['height'] - $h)/2; - break; - - /* 左上角裁剪 */ - case THINKIMAGE_THUMB_NORTHWEST: - //计算缩放比例 - $scale = max($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $x = $y = 0; - $w = $width/$scale; - $h = $height/$scale; - break; - - /* 右下角裁剪 */ - case THINKIMAGE_THUMB_SOUTHEAST: - //计算缩放比例 - $scale = max($width/$w, $height/$h); - - //设置缩略图的坐标及宽度和高度 - $w = $width/$scale; - $h = $height/$scale; - $x = $this->info['width'] - $w; - $y = $this->info['height'] - $h; - break; - - /* 填充 */ - case THINKIMAGE_THUMB_FILLED: - //计算缩放比例 - if($w < $width && $h < $height){ - $scale = 1; - } else { - $scale = min($width/$w, $height/$h); - } - - //设置缩略图的坐标及宽度和高度 - $neww = $w * $scale; - $newh = $h * $scale; - $posx = ($width - $w * $scale)/2; - $posy = ($height - $h * $scale)/2; - - //创建一张新图像 - $newimg = new Imagick(); - $newimg->newImage($width, $height, 'white', $this->info['type']); - - - if('gif' == $this->info['type']){ - $imgs = $this->im->coalesceImages(); - $img = new Imagick(); - $this->im->destroy(); //销毁原图 - - //循环填充每一帧 - do { - //填充图像 - $image = $this->_fill($newimg, $posx, $posy, $neww, $newh, $imgs); - - $img->addImage($image); - $img->setImageDelay($imgs->getImageDelay()); - $img->setImagePage($width, $height, 0, 0); - - $image->destroy(); //销毁零时图片 - - } while ($imgs->nextImage()); - - //压缩图片 - $this->im->destroy(); - $this->im = $img->deconstructImages(); - $imgs->destroy(); //销毁零时图片 - $img->destroy(); //销毁零时图片 - - } else { - //填充图像 - $img = $this->_fill($newimg, $posx, $posy, $neww, $newh); - //销毁原图 - $this->im->destroy(); - $this->im = $img; - } - - //设置新图像属性 - $this->info['width'] = $width; - $this->info['height'] = $height; - return; - - /* 固定 */ - case THINKIMAGE_THUMB_FIXED: - $x = $y = 0; - break; - - default: - throw new Exception('不支持的缩略图裁剪类型'); - } - - /* 裁剪图像 */ - $this->crop($w, $h, $x, $y, $width, $height); - } - - /* 填充指定图像,内部使用 */ - private function _fill($newimg, $posx, $posy, $neww, $newh, $img = null){ - is_null($img) && $img = $this->im; - - /* 将指定图片绘入空白图片 */ - $draw = new ImagickDraw(); - $draw->composite($img->getImageCompose(), $posx, $posy, $neww, $newh, $img); - $image = $newimg->clone(); - $image->drawImage($draw); - $draw->destroy(); - - return $image; - } - - /** - * 添加水印 - * @param string $source 水印图片路径 - * @param integer $locate 水印位置 - * @param integer $alpha 水印透明度 - */ - public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){ - //资源检测 - if(empty($this->im)) throw new Exception('没有可以被添加水印的图像资源'); - if(!is_file($source)) throw new Exception('水印图像不存在'); - - //创建水印图像资源 - $water = new Imagick(realpath($source)); - $info = [$water->getImageWidth(), $water->getImageHeight()]; - - /* 设定水印位置 */ - switch ($locate) { - /* 右下角水印 */ - case THINKIMAGE_WATER_SOUTHEAST: - $x = $this->info['width'] - $info[0]; - $y = $this->info['height'] - $info[1]; - break; - - /* 左下角水印 */ - case THINKIMAGE_WATER_SOUTHWEST: - $x = 0; - $y = $this->info['height'] - $info[1]; - break; - - /* 左上角水印 */ - case THINKIMAGE_WATER_NORTHWEST: - $x = $y = 0; - break; - - /* 右上角水印 */ - case THINKIMAGE_WATER_NORTHEAST: - $x = $this->info['width'] - $info[0]; - $y = 0; - break; - - /* 居中水印 */ - case THINKIMAGE_WATER_CENTER: - $x = ($this->info['width'] - $info[0])/2; - $y = ($this->info['height'] - $info[1])/2; - break; - - /* 下居中水印 */ - case THINKIMAGE_WATER_SOUTH: - $x = ($this->info['width'] - $info[0])/2; - $y = $this->info['height'] - $info[1]; - break; - - /* 右居中水印 */ - case THINKIMAGE_WATER_EAST: - $x = $this->info['width'] - $info[0]; - $y = ($this->info['height'] - $info[1])/2; - break; - - /* 上居中水印 */ - case THINKIMAGE_WATER_NORTH: - $x = ($this->info['width'] - $info[0])/2; - $y = 0; - break; - - /* 左居中水印 */ - case THINKIMAGE_WATER_WEST: - $x = 0; - $y = ($this->info['height'] - $info[1])/2; - break; - - default: - /* 自定义水印坐标 */ - if(is_array($locate)){ - list($x, $y) = $locate; - } else { - throw new Exception('不支持的水印位置类型'); - } - } - - //创建绘图资源 - $draw = new ImagickDraw(); - $draw->composite($water->getImageCompose(), $x, $y, $info[0], $info[1], $water); - - if('gif' == $this->info['type']){ - $img = $this->im->coalesceImages(); - $this->im->destroy(); //销毁原图 - - do{ - //添加水印 - $img->drawImage($draw); - } while ($img->nextImage()); - - //压缩图片 - $this->im = $img->deconstructImages(); - $img->destroy(); //销毁零时图片 - - } else { - //添加水印 - $this->im->drawImage($draw); - } - - //销毁水印资源 - $draw->destroy(); - $water->destroy(); - } - - /** - * 图像添加文字 - * @param string $text 添加的文字 - * @param string $font 字体路径 - * @param integer $size 字号 - * @param string $color 文字颜色 - * @param integer $locate 文字写入位置 - * @param integer $offset 文字相对当前位置的偏移量 - * @param integer $angle 文字倾斜角度 - */ - public function text($text, $font, $size, $color = '#00000000', - $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){ - //资源检测 - if(empty($this->im)) throw new Exception('没有可以被写入文字的图像资源'); - if(!is_file($font)) throw new Exception("不存在的字体文件:{$font}"); - - //获取颜色和透明度 - if(is_array($color)){ - $color = array_map('dechex', $color); - foreach ($color as &$value) { - $value = str_pad($value, 2, '0', STR_PAD_LEFT); - } - $color = '#' . implode('', $color); - } elseif(!is_string($color) || 0 !== strpos($color, '#')) { - throw new Exception('错误的颜色值'); - } - $col = substr($color, 0, 7); - $alp = strlen($color) == 9 ? substr($color, -2) : 0; - - - //获取文字信息 - $draw = new ImagickDraw(); - $draw->setFont(realpath($font)); - $draw->setFontSize($size); - $draw->setFillColor($col); - $draw->setFillAlpha(1-hexdec($alp)/127); - $draw->setTextAntialias(true); - $draw->setStrokeAntialias(true); - - $metrics = $this->im->queryFontMetrics($draw, $text); - - /* 计算文字初始坐标和尺寸 */ - $x = 0; - $y = $metrics['ascender']; - $w = $metrics['textWidth']; - $h = $metrics['textHeight']; - - /* 设定文字位置 */ - switch ($locate) { - /* 右下角文字 */ - case THINKIMAGE_WATER_SOUTHEAST: - $x += $this->info['width'] - $w; - $y += $this->info['height'] - $h; - break; - - /* 左下角文字 */ - case THINKIMAGE_WATER_SOUTHWEST: - $y += $this->info['height'] - $h; - break; - - /* 左上角文字 */ - case THINKIMAGE_WATER_NORTHWEST: - // 起始坐标即为左上角坐标,无需调整 - break; - - /* 右上角文字 */ - case THINKIMAGE_WATER_NORTHEAST: - $x += $this->info['width'] - $w; - break; - - /* 居中文字 */ - case THINKIMAGE_WATER_CENTER: - $x += ($this->info['width'] - $w)/2; - $y += ($this->info['height'] - $h)/2; - break; - - /* 下居中文字 */ - case THINKIMAGE_WATER_SOUTH: - $x += ($this->info['width'] - $w)/2; - $y += $this->info['height'] - $h; - break; - - /* 右居中文字 */ - case THINKIMAGE_WATER_EAST: - $x += $this->info['width'] - $w; - $y += ($this->info['height'] - $h)/2; - break; - - /* 上居中文字 */ - case THINKIMAGE_WATER_NORTH: - $x += ($this->info['width'] - $w)/2; - break; - - /* 左居中文字 */ - case THINKIMAGE_WATER_WEST: - $y += ($this->info['height'] - $h)/2; - break; - - default: - /* 自定义文字坐标 */ - if(is_array($locate)){ - list($posx, $posy) = $locate; - $x += $posx; - $y += $posy; - } else { - throw new Exception('不支持的文字位置类型'); - } - } - - /* 设置偏移量 */ - if(is_array($offset)){ - $offset = array_map('intval', $offset); - list($ox, $oy) = $offset; - } else{ - $offset = intval($offset); - $ox = $oy = $offset; - } - - /* 写入文字 */ - if('gif' == $this->info['type']){ - $img = $this->im->coalesceImages(); - $this->im->destroy(); //销毁原图 - do{ - $img->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text); - } while ($img->nextImage()); - - //压缩图片 - $this->im = $img->deconstructImages(); - $img->destroy(); //销毁零时图片 - - } else { - $this->im->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text); - } - $draw->destroy(); - } - - /** - * 析构方法,用于销毁图像资源 - */ - public function __destruct() { - empty($this->im) || $this->im->destroy(); - } -} \ No newline at end of file diff --git a/Library/Org/Oauth.php b/Library/Org/Oauth.php deleted file mode 100644 index 6f84f217..00000000 --- a/Library/Org/Oauth.php +++ /dev/null @@ -1,72 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org; - -// oauth登录接口 -// -// Oauth::connect('qq',['app_key'=>'','app_secret'=>'','callback'=>'','authorize'=>'']); // 链接QQ登录 -// Oauth::login(); // 跳转到授权登录页面 或者 Oauth::login($callbackUrl); -// Oauth::call('api','params'); // 调用API接口 -// -class Oauth { - - /** - * 操作句柄 - * @var object - * @access protected - */ - static protected $handler = null; - - /** - * 连接oauth - * @access public - * @param string $type Oauth类型 - * @param array $options 配置数组 - * @return object - */ - static public function connect($type,$options=[]) { - $class = 'Org\\Oauth\\Driver\\'.ucwords($type); - self::$handler = new $class($options); - return self::$handler; - } - - // 跳转到授权登录页面 - static public function login($callback=''){ - self::$handler->login($callback); - } - - // 获取access_token - static public function getAccessToken($code){ - self::$handler->getAccessToken($code); - } - - // 设置保存过的token信息 - static public function setToken($token){ - self::$handler->setToken($token); - } - - // 获取oauth用户信息 - static public function getOauthInfo(){ - return self::$handler->getOauthInfo(); - } - - // 获取openid信息 - static public function getOpenId(){ - return self::$handler->getOpenId(); - } - - // 调用oauth接口API - static public function call($api,$param='',$method='GET'){ - return self::$handler->call($api,$param,$method); - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver.php b/Library/Org/Oauth/Driver.php deleted file mode 100644 index 806f155a..00000000 --- a/Library/Org/Oauth/Driver.php +++ /dev/null @@ -1,233 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth; -abstract class Driver { - - /** - * oauth版本 - * @var string - */ - protected $version = '2.0'; - - /** - * 申请应用时分配的app_key - * @var string - */ - protected $appKey = ''; - - /** - * 申请应用时分配的 app_secret - * @var string - */ - protected $appSecret = ''; - - /** - * 授权类型 response_type 目前只能为code - * @var string - */ - protected $responseType = 'code'; - - /** - * grant_type 目前只能为 authorization_code - * @var string - */ - protected $grantType = 'authorization_code'; - - /** - * 获取request_code请求的URL - * @var string - */ - protected $getRequestCodeURL = ''; - - /** - * 获取access_token请求的URL - * @var string - */ - protected $getAccessTokenURL = ''; - - /** - * API根路径 - * @var string - */ - protected $apiBase = ''; - - /** - * 授权后获取到的TOKEN信息 - * @var array - */ - protected $token = null; - - /** - * 回调页面URL 可以通过配置文件配置 - * @var string - */ - protected $callback = ''; - - /** - * 构造方法,配置应用信息 - * @param array $config - */ - public function __construct($config = []){ - $this->appKey = $config['app_key']; - $this->appSecret = $config['app_secret']; - $this->authorize = isset($config['authorize'])?$config['authorize']:''; - $this->callback = isset($config['callback'])?$config['callback']:''; - } - - // 跳转到授权登录页面 - public function login($callback=''){ - if($callback) { - $this->callback = $callback; - } - //跳转到授权页面 - header('Location: ' . $this->getRequestCodeURL()); - exit; - } - - /** - * 请求code - */ - public function getRequestCodeURL(){ - //Oauth 标准参数 - $params = array( - 'client_id' => $this->appKey, - 'redirect_uri' => $this->callback, - 'response_type' => $this->responseType, - ); - - //获取额外参数 - if($this->authorize){ - parse_str($this->authorize, $_param); - if(is_array($_param)){ - $params = array_merge($params, $_param); - } else { - throw new Exception('AUTHORIZE配置不正确!'); - } - } - return $this->getRequestCodeURL . '?' . http_build_query($params); - } - - /** - * 获取access_token - * @param string $code 授权登录成功后得到的code信息 - */ - public function getAccessToken($code){ - $params = array( - 'client_id' => $this->appKey, - 'client_secret' => $this->appSecret, - 'grant_type' => $this->grantType, - 'redirect_uri' => $this->callback, - 'code' => $code, - ); - // 获取token信息 - $data = $this->http($this->getAccessTokenURL, $params, 'POST'); - // 解析token - $this->token = $this->parseToken($data); - return $this->token; - } - - /** - * 设置access_token - * @param string $token - */ - public function setToken($token){ - $this->token = $token; - } - - /** - * 合并默认参数和额外参数 - * @param array $params 默认参数 - * @param array/string $param 额外参数 - * @return array: - */ - protected function param($params, $param){ - if(is_string($param)) - parse_str($param, $param); - return array_merge($params, $param); - } - - /** - * 获取指定API请求的URL - * @param string $api API名称 - * @param string $fix api后缀 - * @return string 请求的完整URL - */ - protected function url($api, $fix = ''){ - return $this->apiBase . $api . $fix; - } - - /** - * 发送HTTP请求方法,目前只支持CURL发送请求 - * @param string $url 请求URL - * @param array $params 请求参数 - * @param string $method 请求方法GET/POST - * @return array $data 响应数据 - */ - protected function http($url, $params, $method = 'GET', $header = [], $multi = false){ - $opts = array( - CURLOPT_TIMEOUT => 30, - CURLOPT_RETURNTRANSFER => 1, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - CURLOPT_HTTPHEADER => $header - ); - - /* 根据请求类型设置特定参数 */ - switch(strtoupper($method)){ - case 'GET': - $opts[CURLOPT_URL] = $url . '?' . http_build_query($params); - break; - case 'POST': - //判断是否传输文件 -+ $params = $multi ? $params : http_build_query($params); - $opts[CURLOPT_URL] = $url; - $opts[CURLOPT_POST] = 1; - $opts[CURLOPT_POSTFIELDS] = $params; - break; - default: - throw new Exception('不支持的请求方式!'); - } - - /* 初始化并执行curl请求 */ - $ch = curl_init(); - curl_setopt_array($ch, $opts); - $data = curl_exec($ch); - $error = curl_error($ch); - curl_close($ch); - if($error) throw new Exception('请求发生错误:' . $error); - return $data; - } - - /** - * 抽象方法,在SNSSDK中实现 - * 组装接口调用参数 并调用接口 - */ - abstract protected function call($api, $param = '', $method = 'GET', $multi = false); - - /** - * 抽象方法,在SNSSDK中实现 - * 解析access_token方法请求后的返回值 - */ - abstract protected function parseToken($result); - - /** - * 抽象方法,在SNSSDK中实现 - * 获取当前授权用户的SNS标识 - */ - abstract public function getOpenId(); - - /** - * 抽象方法 - * 获取当前授权用户的用户信息 - */ - abstract public function getOauthInfo(); -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Baidu.php b/Library/Org/Oauth/Driver/Baidu.php deleted file mode 100644 index 23ed048d..00000000 --- a/Library/Org/Oauth/Driver/Baidu.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Baidu extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://openapi.baidu.com/oauth/2.0/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://openapi.baidu.com/oauth/2.0/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://openapi.baidu.com/rest/2.0/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 百度API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 百度调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $this->openid(); - return $data; - } else - throw new Exception("获取百度ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - $data = $this->call('passport/users/getLoggedInUser'); - return !empty($data['uid'])?$data['uid']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('passport/users/getLoggedInUser'); - - if(!empty($data['uid'])){ - $userInfo['type'] = 'BAIDU'; - $userInfo['name'] = $data['uid']; - $userInfo['nick'] = $data['uname']; - $userInfo['avatar'] = "http://tb.himg.baidu.com/sys/portrait/item/{$data['portrait']}"; - return $userInfo; - } else { - throw new Exception("获取百度用户信息失败:{$data['error_msg']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Diandian.php b/Library/Org/Oauth/Driver/Diandian.php deleted file mode 100644 index 567c7ff6..00000000 --- a/Library/Org/Oauth/Driver/Diandian.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Diandian extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.diandian.com/oauth/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.diandian.com/oauth/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.diandian.com/v1/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 点点网API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 点点网调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['token_type'] && $data['uid']){ - $data['openid'] = $data['uid']; - unset($data['uid']); - return $data; - } else - throw new Exception("获取点点网ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user/info'); - - if(!empty($data['meta']['status']) && $data['meta']['status'] == 200){ - $userInfo['type'] = 'DIANDIAN'; - $userInfo['name'] = $data['response']['name']; - $userInfo['nick'] = $data['response']['name']; - $userInfo['avatar'] = "https://api.diandian.com/v1/blog/{$data['response']['blogs'][0]['blogUuid']}/avatar/144"; - return $userInfo; - } else { - E("获取点点用户信息失败:{$data}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Douban.php b/Library/Org/Oauth/Driver/Douban.php deleted file mode 100644 index f79a051d..00000000 --- a/Library/Org/Oauth/Driver/Douban.php +++ /dev/null @@ -1,91 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Douban extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://www.douban.com/service/auth2/auth'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://www.douban.com/service/auth2/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.douban.com/v2/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 豆瓣调用公共参数 */ - $params = []; - $header = array("Authorization: Bearer {$this->token['access_token']}"); - $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['douban_user_id']){ - $data['openid'] = $data['douban_user_id']; - unset($data['douban_user_id']); - return $data; - } else - throw new Exception("获取豆瓣ACCESS_TOKEN出错:{$data['msg']}"); - } - - /** - * 获取当前授权应用的openid - * @return string|null - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user/~me'); - - if(empty($data['code'])){ - $userInfo['type'] = 'DOUBAN'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['avatar']; - return $userInfo; - } else { - E("获取豆瓣用户信息失败:{$data['msg']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Github.php b/Library/Org/Oauth/Driver/Github.php deleted file mode 100644 index 173b0782..00000000 --- a/Library/Org/Oauth/Driver/Github.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Github extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://github.com/login/oauth/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://github.com/login/oauth/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.github.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* Github 调用公共参数 */ - $params = []; - $header = array("Authorization: bearer {$this->token['access_token']}"); - - $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - parse_str($result, $data); - if($data['access_token'] && $data['token_type']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new Exception("获取 Github ACCESS_TOKEN出错:未知错误"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('user'); - return !empty($data['id'])?$data['id']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user'); - - if(empty($data['code'])){ - $userInfo['type'] = 'GITHUB'; - $userInfo['name'] = $data['login']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['avatar_url']; - return $userInfo; - } else { - E("获取Github用户信息失败:{$data}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Google.php b/Library/Org/Oauth/Driver/Google.php deleted file mode 100644 index f6c2feb8..00000000 --- a/Library/Org/Oauth/Driver/Google.php +++ /dev/null @@ -1,99 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Google extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://accounts.google.com/o/oauth2/auth'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://accounts.google.com/o/oauth2/token'; - - /** - * 获取request_code的额外参数 URL查询字符串格式 - * @var srting - */ - protected $authorize = 'scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://www.googleapis.com/oauth2/v1/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* Google 调用公共参数 */ - $params = []; - $header = array("Authorization: Bearer {$this->token['access_token']}"); - - $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['token_type'] && $data['expires_in']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new Exception("获取 Google ACCESS_TOKEN出错:未知错误"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('userinfo'); - return !empty($data['id'])?$data['id']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('userinfo'); - - if(!empty($data['id'])){ - $userInfo['type'] = 'GOOGLE'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['picture']; - return $userInfo; - } else { - E("获取Google用户信息失败:{$data}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Kaixin.php b/Library/Org/Oauth/Driver/Kaixin.php deleted file mode 100644 index 0445bce8..00000000 --- a/Library/Org/Oauth/Driver/Kaixin.php +++ /dev/null @@ -1,94 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Kaixin extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'http://api.kaixin001.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.kaixin001.com/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.kaixin001.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 开心网API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 开心网调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new Exception("获取开心网ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('users/me'); - return !empty($data['uid'])?$data['uid']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users/me'); - - if(!empty($data['uid'])){ - $userInfo['type'] = 'KAIXIN'; - $userInfo['name'] = $data['uid']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['logo50']; - return $userInfo; - } else { - E("获取开心网用户信息失败:{$data['error']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Msn.php b/Library/Org/Oauth/Driver/Msn.php deleted file mode 100644 index 4d41dcbd..00000000 --- a/Library/Org/Oauth/Driver/Msn.php +++ /dev/null @@ -1,100 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Msn extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://login.live.com/oauth20_authorize.srf'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://login.live.com/oauth20_token.srf'; - - /** - * 获取request_code的额外参数 URL查询字符串格式 - * @var srting - */ - protected $authorize = 'scope=wl.basic wl.offline_access wl.signin wl.emails wl.photos'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://apis.live.net/v5.0/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* MSN 调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['token_type'] && $data['expires_in']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new Exception("获取 MSN ACCESS_TOKEN出错:未知错误"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('me'); - return !empty($data['id'])?$data['id']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('me'); - - if(!empty($data['id'])){ - $userInfo['type'] = 'MSN'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = '微软暂未提供头像URL,请通过 me/picture 接口下载'; - return $userInfo; - } else { - E("获取msn用户信息失败:{$data}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Qq.php b/Library/Org/Oauth/Driver/Qq.php deleted file mode 100644 index ddc48701..00000000 --- a/Library/Org/Oauth/Driver/Qq.php +++ /dev/null @@ -1,102 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Qq extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://graph.qq.com/oauth2.0/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://graph.qq.com/oauth2.0/token'; - - /** - * 获取request_code的额外参数,可在配置中修改 URL查询字符串格式 - * @var srting - */ - protected $authorize = 'scope=get_user_info,add_share'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://graph.qq.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 腾讯QQ调用公共参数 */ - $params = array( - 'oauth_consumer_key' => $this->AppKey, - 'access_token' => $this->token['access_token'], - 'openid' => $this->openid(), - 'format' => 'json' - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - parse_str($result, $data); - if($data['access_token'] && $data['expires_in']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new Exception("获取腾讯QQ ACCESS_TOKEN 出错:{$result}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - if($data['access_token']){ - $data = $this->http($this->url('oauth2.0/me'), array('access_token' => $data['access_token'])); - $data = json_decode(trim(substr($data, 9), " );\n"), true); - if(isset($data['openid'])) - return $data['openid']; - } - return NULL; - } - - public function getOauthInfo(){ - $data = $this->call('user/get_user_info'); - - if($data['ret'] == 0){ - $userInfo['type'] = 'QQ'; - $userInfo['name'] = $data['nickname']; - $userInfo['nick'] = $data['nickname']; - $userInfo['avatar'] = $data['figureurl_2']; - return $userInfo; - } else { - E("获取腾讯QQ用户信息失败:{$data['msg']}"); - } - } -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Renren.php b/Library/Org/Oauth/Driver/Renren.php deleted file mode 100644 index cf87c9d5..00000000 --- a/Library/Org/Oauth/Driver/Renren.php +++ /dev/null @@ -1,116 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Renren extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://graph.renren.com/oauth/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://graph.renren.com/oauth/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'http://api.renren.com/restserver.do'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'POST'){ - /* 人人网调用公共参数 */ - $params = array( - 'method' => $api, - 'access_token' => $this->token['access_token'], - 'v' => '1.0', - 'format' => 'json', - ); - - $data = $this->http($this->url(''), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 合并默认参数和额外参数 - * @param array $params 默认参数 - * @param array/string $param 额外参数 - * @return array: - */ - protected function param($params, $param){ - $params = parent::param($params, $param); - - /* 签名 */ - ksort($params); - $param = []; - foreach ($params as $key => $value){ - $param[] = "{$key}={$value}"; - } - $sign = implode('', $param).$this->AppSecret; - $params['sig'] = md5($sign); - - return $params; - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['user']['id']){ - $data['openid'] = $data['user']['id']; - unset($data['user']); - return $data; - } else - throw new Exception("获取人人网ACCESS_TOKEN出错:{$data['error_description']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users.getInfo'); - - if(!isset($data['error_code'])){ - $userInfo['type'] = 'RENREN'; - $userInfo['name'] = $data[0]['name']; - $userInfo['nick'] = $data[0]['name']; - $userInfo['avatar'] = $data[0]['headurl']; - return $userInfo; - } else { - E("获取人人网用户信息失败:{$data['error_msg']}"); - } - } -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Sina.php b/Library/Org/Oauth/Driver/Sina.php deleted file mode 100644 index f87d4b83..00000000 --- a/Library/Org/Oauth/Driver/Sina.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Sina extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.weibo.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.weibo.com/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.weibo.com/2/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 新浪微博调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['remind_in'] && $data['uid']){ - $data['openid'] = $data['uid']; - unset($data['uid']); - return $data; - } else - throw new Exception("获取新浪微博ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users.getInfo'); - - if(!isset($data['error_code'])){ - $userInfo['type'] = 'RENREN'; - $userInfo['name'] = $data[0]['name']; - $userInfo['nick'] = $data[0]['name']; - $userInfo['avatar'] = $data[0]['headurl']; - return $userInfo; - } else { - E("获取人人网用户信息失败:{$data['error_msg']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Sohu.php b/Library/Org/Oauth/Driver/Sohu.php deleted file mode 100644 index 4d652cf3..00000000 --- a/Library/Org/Oauth/Driver/Sohu.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Sohu extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.sohu.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.sohu.com/oauth2/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.sohu.com/rest/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 搜狐API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 搜狐调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['open_id']){ - $data['openid'] = $data['open_id']; - unset($data['open_id']); - return $data; - } else - throw new Exception("获取搜狐ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('i/prv/1/user/get-basic-info'); - - if('success' == $data['message'] && !empty($data['data'])){ - $userInfo['type'] = 'SOHU'; - $userInfo['name'] = $data['data']['open_id']; - $userInfo['nick'] = $data['data']['nick']; - $userInfo['avatar'] = $data['data']['icon']; - return $userInfo; - } else { - E("获取搜狐用户信息失败:{$data['message']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/T163.php b/Library/Org/Oauth/Driver/T163.php deleted file mode 100644 index f7d35e63..00000000 --- a/Library/Org/Oauth/Driver/T163.php +++ /dev/null @@ -1,95 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class T163 extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.t.163.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.t.163.com/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.t.163.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 新浪微博调用公共参数 */ - $params = array( - 'oauth_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['uid'] && $data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $data['uid']; - unset($data['uid']); - return $data; - } else - throw new Exception("获取网易微博ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('users/show'); - return !empty($data['id'])?$data['id']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users/show'); - - if($data['error_code'] == 0){ - $userInfo['type'] = 'T163'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['screen_name']; - $userInfo['avatar'] = str_replace('w=48&h=48', 'w=180&h=180', $data['profile_image_url']); - return $userInfo; - } else { - E("获取网易微博用户信息失败:{$data['error']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Taobao.php b/Library/Org/Oauth/Driver/Taobao.php deleted file mode 100644 index fb7cc325..00000000 --- a/Library/Org/Oauth/Driver/Taobao.php +++ /dev/null @@ -1,97 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Taobao extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://oauth.taobao.com/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://oauth.taobao.com/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://eco.taobao.com/router/rest'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 淘宝网调用公共参数 */ - $params = array( - 'method' => $api, - 'access_token' => $this->token['access_token'], - 'format' => 'json', - 'v' => '2.0', - ); - $data = $this->http($this->url(''), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['taobao_user_id']){ - $data['openid'] = $data['taobao_user_id']; - unset($data['taobao_user_id']); - return $data; - } else - throw new Exception("获取淘宝网ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $fields = 'user_id,nick,sex,buyer_credit,avatar,has_shop,vip_info'; - $data = $this->call('taobao.user.buyer.get', "fields={$fields}"); - - if(!empty($data['user_buyer_get_response']['user'])){ - $user = $data['user_buyer_get_response']['user']; - $userInfo['type'] = 'TAOBAO'; - $userInfo['name'] = $user['user_id']; - $userInfo['nick'] = $user['nick']; - $userInfo['avatar'] = $user['avatar']; - return $userInfo; - } else { - E("获取淘宝网用户信息失败:{$data['error_response']['msg']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/Tencent.php b/Library/Org/Oauth/Driver/Tencent.php deleted file mode 100644 index 1fd07a0a..00000000 --- a/Library/Org/Oauth/Driver/Tencent.php +++ /dev/null @@ -1,98 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class Tencent extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://open.t.qq.com/cgi-bin/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://open.t.qq.com/cgi-bin/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://open.t.qq.com/api/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 腾讯微博调用公共参数 */ - $params = array( - 'oauth_consumer_key' => $this->AppKey, - 'access_token' => $this->token['access_token'], - 'openid' => $this->openid(), - 'clientip' => get_client_ip(), - 'oauth_version' => '2.a', - 'scope' => 'all', - 'format' => 'json' - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - parse_str($result, $data); - $data = array_merge($data, ['openid' => $_GET['openid'], 'openkey' => $_GET['openkey']]); - if($data['access_token'] && $data['expires_in'] && $data['openid']) - return $data; - else - throw new Exception("获取腾讯微博 ACCESS_TOKEN 出错:{$result}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users.getInfo'); - - if(!isset($data['error_code'])){ - $userInfo['type'] = 'RENREN'; - $userInfo['name'] = $data[0]['name']; - $userInfo['nick'] = $data[0]['name']; - $userInfo['avatar'] = $data[0]['headurl']; - return $userInfo; - } else { - E("获取人人网用户信息失败:{$data['error_msg']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Oauth/Driver/X360.php b/Library/Org/Oauth/Driver/X360.php deleted file mode 100644 index 64d6e0ed..00000000 --- a/Library/Org/Oauth/Driver/X360.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org\Oauth\Driver; -use Org\Oauth\Driver; - -class X360 extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://openapi.360.cn/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://openapi.360.cn/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://openapi.360.cn/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 360开放平台API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 360开放平台调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new Exception("获取360开放平台ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - $data = $this->call('user/me'); - return !empty($data['id'])?$data['id']:NULL; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user/me'); - - if($data['error_code'] == 0){ - $userInfo['type'] = 'X360'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['avatar']; - return $userInfo; - } else { - E("获取360用户信息失败:{$data['error']}"); - } - } - -} \ No newline at end of file diff --git a/Library/Org/Parser.php b/Library/Org/Parser.php deleted file mode 100644 index 428ef27e..00000000 --- a/Library/Org/Parser.php +++ /dev/null @@ -1,32 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org; - -// 内容解析类 -class Parser { - - static private $handler = []; - - // 解析内容 - static public function parse($content,$type){ - if(!isset(self::$handler[$type])) { - $class = '\\Org\\Parser\\Driver\\'.ucwords($type); - self::$handler[$type] = new $class(); - } - return self::$handler[$type]->parse($content); - } - - // 调用驱动类的方法 - static public function __callStatic($method, $params){ - return self::parse($params[0],$method); - } -} \ No newline at end of file diff --git a/Library/Org/Parser/Driver/Markdown.php b/Library/Org/Parser/Driver/Markdown.php deleted file mode 100644 index cd7115c1..00000000 --- a/Library/Org/Parser/Driver/Markdown.php +++ /dev/null @@ -1,1534 +0,0 @@ - -# -# Original Markdown -# Copyright (c) 2004-2006 John Gruber -# -# - -# 应用到ThinkPHP中,因而修改为ThinkPHP规范的命名空间 -# namespace Michelf; -namespace Org\Parser\Driver; - -# -# The following two constants are deprecated: avoid using them, they'll -# disappear when the Lib branch becomes the only one to be updated. -# -# You can get the parser's version using the constant inside of the parser -# class: \Michelf\Markdown::MARKDOWNLIB_VERSION. -# - -const MARKDOWN_VERSION = "1.0.1p"; # Sun 13 Jan 2013 -const MARKDOWNEXTRA_VERSION = "1.2.6"; # Sun 13 Jan 2013 - -# -# Markdown Parser Class -# - -class Markdown { - - ### Version ### - - public const MARKDOWNLIB_VERSION = "1.3-beta4"; - - ### Simple Function Interface ### - - public static function defaultTransform($text) { - # - # Initialize the parser and return the result of its transform method. - # This will work fine for derived classes too. - # - # Take parser class on which this function was called. - $parser_class = \get_called_class(); - - # try to take parser from the static parser list - static $parser_list; - $parser =& $parser_list[$parser_class]; - - # create the parser it not already set - if (!$parser) - $parser = new $parser_class; - - # Transform text using parser. - return $parser->transform($text); - } - - ### Configuration Variables ### - - # Change to ">" for HTML output. - public $empty_element_suffix = " />"; - public $tab_width = 4; - - # Change to `true` to disallow markup or entities. - public $no_markup = false; - public $no_entities = false; - - # Predefined urls and titles for reference links and images. - public $predef_urls = array(); - public $predef_titles = array(); - - - ### Parser Implementation ### - - # Regex to match balanced [brackets]. - # Needed to insert a maximum bracked depth while converting to PHP. - protected $nested_brackets_depth = 6; - protected $nested_brackets_re; - - protected $nested_url_parenthesis_depth = 4; - protected $nested_url_parenthesis_re; - - # Table of hash values for escaped characters: - protected $escape_chars = '\`*_{}[]()>#+-.!'; - protected $escape_chars_re; - - - public function __construct() { - # - # Constructor function. Initialize appropriate member variables. - # - $this->_initDetab(); - $this->prepareItalicsAndBold(); - - $this->nested_brackets_re = - str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). - str_repeat('\])*', $this->nested_brackets_depth); - - $this->nested_url_parenthesis_re = - str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). - str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); - - $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; - - # Sort document, block, and span gamut in ascendent priority order. - asort($this->document_gamut); - asort($this->block_gamut); - asort($this->span_gamut); - } - - - # Internal hashes used during transformation. - protected $urls = array(); - protected $titles = array(); - protected $html_hashes = array(); - - # Status flag to avoid invalid nesting. - protected $in_anchor = false; - - - protected function setup() { - # - # Called before the transformation process starts to setup parser - # states. - # - # Clear global hashes. - $this->urls = $this->predef_urls; - $this->titles = $this->predef_titles; - $this->html_hashes = array(); - - $this->in_anchor = false; - } - - protected function teardown() { - # - # Called after the transformation process to clear any variable - # which may be taking up memory unnecessarly. - # - $this->urls = array(); - $this->titles = array(); - $this->html_hashes = array(); - } - - /** - * 提供给ThinkPHP外部调用的方法,麦当苗儿为ThinkPHP添加 - * @author - * @param string $content 需要解析的Markdown字符串 - * @return string 解析后的HTML字符串 - */ - public function parse($content){ - return $this->transform($content); - } - - protected function transform($text) { - # - # Main function. Performs some preprocessing on the input text - # and pass it through the document gamut. - # - $this->setup(); - - # Remove UTF-8 BOM and marker character in input, if present. - $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); - - # Standardize line endings: - # DOS to Unix and Mac to Unix - $text = preg_replace('{\r\n?}', "\n", $text); - - # Make sure $text ends with a couple of newlines: - $text .= "\n\n"; - - # Convert all tabs to spaces. - $text = $this->detab($text); - - # Turn block-level HTML blocks into hash entries - $text = $this->hashHTMLBlocks($text); - - # Strip any lines consisting only of spaces and tabs. - # This makes subsequent regexen easier to write, because we can - # match consecutive blank lines with /\n+/ instead of something - # contorted like /[ ]*\n+/ . - $text = preg_replace('/^[ ]+$/m', '', $text); - - # Run document gamut methods. - foreach ($this->document_gamut as $method => $priority) { - $text = $this->$method($text); - } - - $this->teardown(); - - return $text . "\n"; - } - - protected $document_gamut = array( - # Strip link definitions, store in hashes. - "stripLinkDefinitions" => 20, - - "runBasicBlockGamut" => 30, - ); - - - protected function stripLinkDefinitions($text) { - # - # Strips link definitions from text, stores the URLs and titles in - # hash references. - # - $less_than_tab = $this->tab_width - 1; - - # Link defs are in the form: ^[id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 - [ ]* - \n? # maybe *one* newline - [ ]* - (?: - <(.+?)> # url = $2 - | - (\S+?) # url = $3 - ) - [ ]* - \n? # maybe one newline - [ ]* - (?: - (?<=\s) # lookbehind for whitespace - ["(] - (.*?) # title = $4 - [")] - [ ]* - )? # title is optional - (?:\n+|\Z) - }xm', - array(&$this, '_stripLinkDefinitions_callback'), - $text); - return $text; - } - protected function _stripLinkDefinitions_callback($matches) { - $link_id = strtolower($matches[1]); - $url = $matches[2] == '' ? $matches[3] : $matches[2]; - $this->urls[$link_id] = $url; - $this->titles[$link_id] =& $matches[4]; - return ''; # String that will replace the block - } - - - protected function hashHTMLBlocks($text) { - if ($this->no_markup) return $text; - - $less_than_tab = $this->tab_width - 1; - - # Hashify HTML blocks: - # We only want to do this for block-level HTML tags, such as headers, - # lists, and tables. That's because we still want to wrap

s around - # "paragraphs" that are wrapped in non-block-level tags, such as anchors, - # phrase emphasis, and spans. The list of tags we're looking for is - # hard-coded: - # - # * List "a" is made of tags which can be both inline or block-level. - # These will be treated block-level when the start tag is alone on - # its line, otherwise they're not matched here and will be taken as - # inline later. - # * List "b" is made of tags which are always block-level; - # - $block_tags_a_re = 'ins|del'; - $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. - 'script|noscript|form|fieldset|iframe|math|svg|'. - 'article|section|nav|aside|hgroup|header|footer|'. - 'figure'; - - # Regular expression for the content of a block tag. - $nested_tags_level = 4; - $attr = ' - (?> # optional tag attributes - \s # starts with whitespace - (?> - [^>"/]+ # text outside quotes - | - /+(?!>) # slash not followed by ">" - | - "[^"]*" # text inside double quotes (tolerate ">") - | - \'[^\']*\' # text inside single quotes (tolerate ">") - )* - )? - '; - $content = - str_repeat(' - (?> - [^<]+ # content without tag - | - <\2 # nested opening tag - '.$attr.' # attributes - (?> - /> - | - >', $nested_tags_level). # end of opening tag - '.*?'. # last level nested tag content - str_repeat(' - # closing nested tag - ) - | - <(?!/\2\s*> # other tags with a different name - ) - )*', - $nested_tags_level); - $content2 = str_replace('\2', '\3', $content); - - # First, look for nested blocks, e.g.: - #

- #
- # tags for inner block must be indented. - #
- #
- # - # The outermost tags must start at the left margin for this to match, and - # the inner nested divs must be indented. - # We need to do this before the next, more liberal match, because the next - # match will start at the first `
` and stop at the first `
`. - $text = preg_replace_callback('{(?> - (?> - (?<=\n\n) # Starting after a blank line - | # or - \A\n? # the beginning of the doc - ) - ( # save in $1 - - # Match from `\n` to `\n`, handling nested tags - # in between. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_b_re.')# start tag = $2 - '.$attr.'> # attributes followed by > and \n - '.$content.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special version for tags of group a. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_a_re.')# start tag = $3 - '.$attr.'>[ ]*\n # attributes followed by > - '.$content2.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special case just for
. It was easier to make a special - # case than to make the other regex more complicated. - - [ ]{0,'.$less_than_tab.'} - <(hr) # start tag = $2 - '.$attr.' # attributes - /?> # the matching end tag - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # Special case for standalone HTML comments: - - [ ]{0,'.$less_than_tab.'} - (?s: - - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # PHP and ASP-style processor instructions ( - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - ) - )}Sxmi', - array(&$this, '_hashHTMLBlocks_callback'), - $text); - - return $text; - } - protected function _hashHTMLBlocks_callback($matches) { - $text = $matches[1]; - $key = $this->hashBlock($text); - return "\n\n$key\n\n"; - } - - - protected function hashPart($text, $boundary = 'X') { - # - # Called whenever a tag must be hashed when a function insert an atomic - # element in the text stream. Passing $text to through this function gives - # a unique text-token which will be reverted back when calling unhash. - # - # The $boundary argument specify what character should be used to surround - # the token. By convension, "B" is used for block elements that needs not - # to be wrapped into paragraph tags at the end, ":" is used for elements - # that are word separators and "X" is used in the general case. - # - # Swap back any tag hash found in $text so we do not have to `unhash` - # multiple times at the end. - $text = $this->unhash($text); - - # Then hash the block. - static $i = 0; - $key = "$boundary\x1A" . ++$i . $boundary; - $this->html_hashes[$key] = $text; - return $key; # String that will replace the tag. - } - - - protected function hashBlock($text) { - # - # Shortcut function for hashPart with block-level boundaries. - # - return $this->hashPart($text, 'B'); - } - - - protected $block_gamut = array( - # - # These are all the transformations that form block-level - # tags like paragraphs, headers, and list items. - # - "doHeaders" => 10, - "doHorizontalRules" => 20, - - "doLists" => 40, - "doCodeBlocks" => 50, - "doBlockQuotes" => 60, - ); - - protected function runBlockGamut($text) { - # - # Run block gamut tranformations. - # - # We need to escape raw HTML in Markdown source before doing anything - # else. This need to be done for each block, and not only at the - # begining in the Markdown function since hashed blocks can be part of - # list items and could have been indented. Indented blocks would have - # been seen as a code block in a previous pass of hashHTMLBlocks. - $text = $this->hashHTMLBlocks($text); - - return $this->runBasicBlockGamut($text); - } - - protected function runBasicBlockGamut($text) { - # - # Run block gamut tranformations, without hashing HTML blocks. This is - # useful when HTML blocks are known to be already hashed, like in the first - # whole-document pass. - # - foreach ($this->block_gamut as $method => $priority) { - $text = $this->$method($text); - } - - # Finally form paragraph and restore hashed blocks. - $text = $this->formParagraphs($text); - - return $text; - } - - - protected function doHorizontalRules($text) { - # Do Horizontal Rules: - return preg_replace( - '{ - ^[ ]{0,3} # Leading space - ([-*_]) # $1: First marker - (?> # Repeated marker group - [ ]{0,2} # Zero, one, or two spaces. - \1 # Marker character - ){2,} # Group repeated at least twice - [ ]* # Tailing spaces - $ # End of line. - }mx', - "\n".$this->hashBlock("empty_element_suffix")."\n", - $text); - } - - - protected $span_gamut = array( - # - # These are all the transformations that occur *within* block-level - # tags like paragraphs, headers, and list items. - # - # Process character escapes, code spans, and inline HTML - # in one shot. - "parseSpan" => -30, - - # Process anchor and image tags. Images must come first, - # because ![foo][f] looks like an anchor. - "doImages" => 10, - "doAnchors" => 20, - - # Make links out of things like `` - # Must come after doAnchors, because you can use < and > - # delimiters in inline links like [this](). - "doAutoLinks" => 30, - "encodeAmpsAndAngles" => 40, - - "doItalicsAndBold" => 50, - "doHardBreaks" => 60, - ); - - protected function runSpanGamut($text) { - # - # Run span gamut tranformations. - # - foreach ($this->span_gamut as $method => $priority) { - $text = $this->$method($text); - } - - return $text; - } - - - protected function doHardBreaks($text) { - # Do hard breaks: - return preg_replace_callback('/ {2,}\n/', - array(&$this, '_doHardBreaks_callback'), $text); - } - protected function _doHardBreaks_callback($matches) { - return $this->hashPart("empty_element_suffix\n"); - } - - - protected function doAnchors($text) { - # - # Turn Markdown link shortcuts into XHTML tags. - # - if ($this->in_anchor) return $text; - $this->in_anchor = true; - - # - # First, handle reference-style links: [link text] [id] - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - ) - }xs', - array(&$this, '_doAnchors_reference_callback'), $text); - - # - # Next, inline-style links: [link text](url "optional title") - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - \( # literal paren - [ \n]* - (?: - <(.+?)> # href = $3 - | - ('.$this->nested_url_parenthesis_re.') # href = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # Title = $7 - \6 # matching quote - [ \n]* # ignore any spaces/tabs between closing quote and ) - )? # title is optional - \) - ) - }xs', - array(&$this, '_doAnchors_inline_callback'), $text); - - # - # Last, handle reference-style shortcuts: [link text] - # These must come last in case you've also got [link text][1] - # or [link text](/foo) - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ([^\[\]]+) # link text = $2; can\'t contain [ or ] - \] - ) - }xs', - array(&$this, '_doAnchors_reference_callback'), $text); - - $this->in_anchor = false; - return $text; - } - protected function _doAnchors_reference_callback($matches) { - $whole_match = $matches[1]; - $link_text = $matches[2]; - $link_id =& $matches[3]; - - if ($link_id == "") { - # for shortcut links like [this][] or [this]. - $link_id = $link_text; - } - - # lower-case and turn embedded newlines into spaces - $link_id = strtolower($link_id); - $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); - - if (isset($this->urls[$link_id])) { - $url = $this->urls[$link_id]; - $url = $this->encodeAttribute($url); - - $result = "titles[$link_id] ) ) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - $result = $this->hashPart($result); - } - else { - $result = $whole_match; - } - return $result; - } - protected function _doAnchors_inline_callback($matches) { - $whole_match = $matches[1]; - $link_text = $this->runSpanGamut($matches[2]); - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $url = $this->encodeAttribute($url); - - $result = "encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - - return $this->hashPart($result); - } - - - protected function doImages($text) { - # - # Turn Markdown image shortcuts into tags. - # - # - # First, handle reference-style labeled images: ![alt text][id] - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - - ) - }xs', - array(&$this, '_doImages_reference_callback'), $text); - - # - # Next, handle inline images: ![alt text](url "optional title") - # Don't forget: encode * and _ - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - \s? # One optional whitespace character - \( # literal paren - [ \n]* - (?: - <(\S*)> # src url = $3 - | - ('.$this->nested_url_parenthesis_re.') # src url = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # title = $7 - \6 # matching quote - [ \n]* - )? # title is optional - \) - ) - }xs', - array(&$this, '_doImages_inline_callback'), $text); - - return $text; - } - protected function _doImages_reference_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $link_id = strtolower($matches[3]); - - if ($link_id == "") { - $link_id = strtolower($alt_text); # for shortcut links like ![this][]. - } - - $alt_text = $this->encodeAttribute($alt_text); - if (isset($this->urls[$link_id])) { - $url = $this->encodeAttribute($this->urls[$link_id]); - $result = "\"$alt_text\"";titles[$link_id])) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - $result .= $this->empty_element_suffix; - $result = $this->hashPart($result); - } - else { - # If there's no such link ID, leave intact: - $result = $whole_match; - } - - return $result; - } - protected function _doImages_inline_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $alt_text = $this->encodeAttribute($alt_text); - $url = $this->encodeAttribute($url); - $result = "\"$alt_text\"";encodeAttribute($title); - $result .= " title=\"$title\""; # $title already quoted - } - $result .= $this->empty_element_suffix; - - return $this->hashPart($result); - } - - - protected function doHeaders($text) { - # Setext-style headers: - # Header 1 - # ======== - # - # Header 2 - # -------- - # - $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', - array(&$this, '_doHeaders_callback_setext'), $text); - - # atx-style headers: - # # Header 1 - # ## Header 2 - # ## Header 2 with closing hashes ## - # ... - # ###### Header 6 - # - $text = preg_replace_callback('{ - ^(\#{1,6}) # $1 = string of #\'s - [ ]* - (.+?) # $2 = Header text - [ ]* - \#* # optional closing #\'s (not counted) - \n+ - }xm', - array(&$this, '_doHeaders_callback_atx'), $text); - - return $text; - } - protected function _doHeaders_callback_setext($matches) { - # Terrible hack to check we haven't found an empty list item. - if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) - return $matches[0]; - - $level = $matches[2]{0} == '=' ? 1 : 2; - $block = "".$this->runSpanGamut($matches[1]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - protected function _doHeaders_callback_atx($matches) { - $level = strlen($matches[1]); - $block = "".$this->runSpanGamut($matches[2]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - - protected function doLists($text) { - # - # Form HTML ordered (numbered) and unordered (bulleted) lists. - # - $less_than_tab = $this->tab_width - 1; - - # Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - - $markers_relist = array( - $marker_ul_re => $marker_ol_re, - $marker_ol_re => $marker_ul_re, - ); - - foreach ($markers_relist as $marker_re => $other_marker_re) { - # Re-usable pattern to match any entirel ul or ol list: - $whole_list_re = ' - ( # $1 = whole list - ( # $2 - ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces - ('.$marker_re.') # $4 = first list item marker - [ ]+ - ) - (?s:.+?) - ( # $5 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another list item marker - [ ]* - '.$marker_re.'[ ]+ - ) - | - (?= # Lookahead for another kind of list - \n - \3 # Must have the same indentation - '.$other_marker_re.'[ ]+ - ) - ) - ) - '; // mx - - # We use a different prefix before nested lists than top-level lists. - # See extended comment in _ProcessListItems(). - - if ($this->list_level) { - $text = preg_replace_callback('{ - ^ - '.$whole_list_re.' - }mx', - array(&$this, '_doLists_callback'), $text); - } - else { - $text = preg_replace_callback('{ - (?:(?<=\n)\n|\A\n?) # Must eat the newline - '.$whole_list_re.' - }mx', - array(&$this, '_doLists_callback'), $text); - } - } - - return $text; - } - protected function _doLists_callback($matches) { - # Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - - $list = $matches[1]; - $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; - - $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); - - $list .= "\n"; - $result = $this->processListItems($list, $marker_any_re); - - $result = $this->hashBlock("<$list_type>\n" . $result . ""); - return "\n". $result ."\n\n"; - } - - protected $list_level = 0; - - protected function processListItems($list_str, $marker_any_re) { - # - # Process the contents of a single ordered or unordered list, splitting it - # into individual list items. - # - # The $this->list_level global keeps track of when we're inside a list. - # Each time we enter a list, we increment it; when we leave a list, - # we decrement. If it's zero, we're not in a list anymore. - # - # We do this because when we're not inside a list, we want to treat - # something like this: - # - # I recommend upgrading to version - # 8. Oops, now this line is treated - # as a sub-list. - # - # As a single paragraph, despite the fact that the second line starts - # with a digit-period-space sequence. - # - # Whereas when we're inside a list (or sub-list), that line will be - # treated as the start of a sub-list. What a kludge, huh? This is - # an aspect of Markdown's syntax that's hard to parse perfectly - # without resorting to mind-reading. Perhaps the solution is to - # change the syntax rules such that sub-lists must start with a - # starting cardinal number; e.g. "1." or "a.". - - $this->list_level++; - - # trim trailing blank lines: - $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); - - $list_str = preg_replace_callback('{ - (\n)? # leading line = $1 - (^[ ]*) # leading whitespace = $2 - ('.$marker_any_re.' # list marker and space = $3 - (?:[ ]+|(?=\n)) # space only required if item is not empty - ) - ((?s:.*?)) # list item text = $4 - (?:(\n+(?=\n))|\n) # tailing blank line = $5 - (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) - }xm', - array(&$this, '_processListItems_callback'), $list_str); - - $this->list_level--; - return $list_str; - } - protected function _processListItems_callback($matches) { - $item = $matches[4]; - $leading_line =& $matches[1]; - $leading_space =& $matches[2]; - $marker_space = $matches[3]; - $tailing_blank_line =& $matches[5]; - - if ($leading_line || $tailing_blank_line || - preg_match('/\n{2,}/', $item)) - { - # Replace marker with the appropriate whitespace indentation - $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; - $item = $this->runBlockGamut($this->outdent($item)."\n"); - } - else { - # Recursion for sub-lists: - $item = $this->doLists($this->outdent($item)); - $item = preg_replace('/\n+$/', '', $item); - $item = $this->runSpanGamut($item); - } - - return "
  • " . $item . "
  • \n"; - } - - - protected function doCodeBlocks($text) { - # - # Process Markdown `
    ` blocks.
    -	#
    -		$text = preg_replace_callback('{
    -				(?:\n\n|\A\n?)
    -				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    -				  (?>
    -					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    -					.*\n+
    -				  )+
    -				)
    -				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    -			}xm',
    -			array(&$this, '_doCodeBlocks_callback'), $text);
    -
    -		return $text;
    -	}
    -	protected function _doCodeBlocks_callback($matches) {
    -		$codeblock = $matches[1];
    -
    -		$codeblock = $this->outdent($codeblock);
    -		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    -
    -		# trim leading newlines and trailing newlines
    -		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    -
    -		$codeblock = "
    $codeblock\n
    "; - return "\n\n".$this->hashBlock($codeblock)."\n\n"; - } - - - protected function makeCodeSpan($code) { - # - # Create a code span markup for $code. Called from handleSpanToken. - # - $code = htmlspecialchars(trim($code), ENT_NOQUOTES); - return $this->hashPart("$code"); - } - - - protected $em_relist = array( - '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { - foreach ($this->strong_relist as $strong => $strong_re) { - # Construct list of allowed token expressions. - $token_relist = array(); - if (isset($this->em_strong_relist["$em$strong"])) { - $token_relist[] = $this->em_strong_relist["$em$strong"]; - } - $token_relist[] = $em_re; - $token_relist[] = $strong_re; - - # Construct master expression from list. - $token_re = '{('. implode('|', $token_relist) .')}'; - $this->em_strong_prepared_relist["$em$strong"] = $token_re; - } - } - } - - protected function doItalicsAndBold($text) { - $token_stack = array(''); - $text_stack = array(''); - $em = ''; - $strong = ''; - $tree_char_em = false; - - while (1) { - # - # Get prepared regular expression for seraching emphasis tokens - # in current context. - # - $token_re = $this->em_strong_prepared_relist["$em$strong"]; - - # - # Each loop iteration search for the next emphasis token. - # Each token is then passed to handleSpanToken. - # - $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); - $text_stack[0] .= $parts[0]; - $token =& $parts[1]; - $text =& $parts[2]; - - if (empty($token)) { - # Reached end of text span: empty stack without emitting. - # any more emphasis. - while ($token_stack[0]) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - break; - } - - $token_len = strlen($token); - if ($tree_char_em) { - # Reached closing marker while inside a three-char emphasis. - if ($token_len == 3) { - # Three-char closing marker, close em and strong. - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - $strong = ''; - } else { - # Other closing marker: close one em or strong and - # change current token state to match the other - $token_stack[0] = str_repeat($token{0}, 3-$token_len); - $tag = $token_len == 2 ? "strong" : "em"; - $span = $text_stack[0]; - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] = $this->hashPart($span); - $$tag = ''; # $$tag stands for $em or $strong - } - $tree_char_em = false; - } else if ($token_len == 3) { - if ($em) { - # Reached closing marker for both em and strong. - # Closing strong marker: - for ($i = 0; $i < 2; ++$i) { - $shifted_token = array_shift($token_stack); - $tag = strlen($shifted_token) == 2 ? "strong" : "em"; - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] .= $this->hashPart($span); - $$tag = ''; # $$tag stands for $em or $strong - } - } else { - # Reached opening three-char emphasis marker. Push on token - # stack; will be handled by the special condition above. - $em = $token{0}; - $strong = "$em$em"; - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $tree_char_em = true; - } - } else if ($token_len == 2) { - if ($strong) { - # Unwind any dangling emphasis marker: - if (strlen($token_stack[0]) == 1) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - # Closing strong marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $strong = ''; - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $strong = $token; - } - } else { - # Here $token_len == 1 - if ($em) { - if (strlen($token_stack[0]) == 1) { - # Closing emphasis marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - } else { - $text_stack[0] .= $token; - } - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $em = $token; - } - } - } - return $text_stack[0]; - } - - - protected function doBlockQuotes($text) { - $text = preg_replace_callback('/ - ( # Wrap whole match in $1 - (?> - ^[ ]*>[ ]? # ">" at the start of a line - .+\n # rest of the first line - (.+\n)* # subsequent consecutive lines - \n* # blanks - )+ - ) - /xm', - array(&$this, '_doBlockQuotes_callback'), $text); - - return $text; - } - protected function _doBlockQuotes_callback($matches) { - $bq = $matches[1]; - # trim one level of quoting - trim whitespace-only lines - $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); - $bq = $this->runBlockGamut($bq); # recurse - - $bq = preg_replace('/^/m', " ", $bq); - # These leading spaces cause problem with
     content, 
    -		# so we need to fix that:
    -		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', - array(&$this, '_doBlockQuotes_callback2'), $bq); - - return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; - } - protected function _doBlockQuotes_callback2($matches) { - $pre = $matches[1]; - $pre = preg_replace('/^ /m', '', $pre); - return $pre; - } - - - protected function formParagraphs($text) { - # - # Params: - # $text - string to process with html

    tags - # - # Strip leading and trailing lines: - $text = preg_replace('/\A\n+|\n+\z/', '', $text); - - $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); - - # - # Wrap

    tags and unhashify HTML blocks - # - foreach ($grafs as $key => $value) { - if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { - # Is a paragraph. - $value = $this->runSpanGamut($value); - $value = preg_replace('/^([ ]*)/', "

    ", $value); - $value .= "

    "; - $grafs[$key] = $this->unhash($value); - } - else { - # Is a block. - # Modify elements of @grafs in-place... - $graf = $value; - $block = $this->html_hashes[$graf]; - $graf = $block; -// if (preg_match('{ -// \A -// ( # $1 =
    tag -//
    ]* -// \b -// markdown\s*=\s* ([\'"]) # $2 = attr quote char -// 1 -// \2 -// [^>]* -// > -// ) -// ( # $3 = contents -// .* -// ) -// (
    ) # $4 = closing tag -// \z -// }xs', $block, $matches)) -// { -// list(, $div_open, , $div_content, $div_close) = $matches; -// -// # We can't call Markdown(), because that resets the hash; -// # that initialization code should be pulled into its own sub, though. -// $div_content = $this->hashHTMLBlocks($div_content); -// -// # Run document gamut methods on the content. -// foreach ($this->document_gamut as $method => $priority) { -// $div_content = $this->$method($div_content); -// } -// -// $div_open = preg_replace( -// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); -// -// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; -// } - $grafs[$key] = $graf; - } - } - - return implode("\n\n", $grafs); - } - - - protected function encodeAttribute($text) { - # - # Encode text for a double-quoted HTML attribute. This function - # is *not* suitable for attributes enclosed in single quotes. - # - $text = $this->encodeAmpsAndAngles($text); - $text = str_replace('"', '"', $text); - return $text; - } - - - protected function encodeAmpsAndAngles($text) { - # - # Smart processing for ampersands and angle brackets that need to - # be encoded. Valid character entities are left alone unless the - # no-entities mode is set. - # - if ($this->no_entities) { - $text = str_replace('&', '&', $text); - } else { - # Ampersand-encoding based entirely on Nat Irons's Amputator - # MT plugin: - $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', - '&', $text);; - } - # Encode remaining <'s - $text = str_replace('<', '<', $text); - - return $text; - } - - - protected function doAutoLinks($text) { - $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', - array(&$this, '_doAutoLinks_url_callback'), $text); - - # Email addresses: - $text = preg_replace_callback('{ - < - (?:mailto:)? - ( - (?: - [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ - | - ".*?" - ) - \@ - (?: - [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ - | - \[[\d.a-fA-F:]+\] # IPv4 & IPv6 - ) - ) - > - }xi', - array(&$this, '_doAutoLinks_email_callback'), $text); - - return $text; - } - protected function _doAutoLinks_url_callback($matches) { - $url = $this->encodeAttribute($matches[1]); - $link = "$url"; - return $this->hashPart($link); - } - protected function _doAutoLinks_email_callback($matches) { - $address = $matches[1]; - $link = $this->encodeEmailAddress($address); - return $this->hashPart($link); - } - - - protected function encodeEmailAddress($addr) { - # - # Input: an email address, e.g. "foo@example.com" - # - # Output: the email address as a mailto link, with each character - # of the address encoded as either a decimal or hex entity, in - # the hopes of foiling most address harvesting spam bots. E.g.: - # - #

    foo@exampl - # e.com

    - # - # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. - # With some optimizations by Milian Wolff. - # - $addr = "mailto:" . $addr; - $chars = preg_split('/(? $char) { - $ord = ord($char); - # Ignore non-ascii chars. - if ($ord < 128) { - $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. - # roughly 10% raw, 45% hex, 45% dec - # '@' *must* be encoded. I insist. - if ($r > 90 && $char != '@') /* do nothing */; - else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; - else $chars[$key] = '&#'.$ord.';'; - } - } - - $addr = implode('', $chars); - $text = implode('', array_slice($chars, 7)); # text without `mailto:` - $addr = "$text"; - - return $addr; - } - - - protected function parseSpan($str) { - # - # Take the string $str and parse it into tokens, hashing embeded HTML, - # escaped characters and handling code spans. - # - $output = ''; - - $span_re = '{ - ( - \\\\'.$this->escape_chars_re.' - | - (?no_markup ? '' : ' - | - # comment - | - <\?.*?\?> | <%.*?%> # processing instruction - | - <[!$]?[-a-zA-Z0-9:_]+ # regular tags - (?> - \s - (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* - )? - > - | - <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag - | - # closing tag - ').' - ) - }xs'; - - while (1) { - # - # Each loop iteration seach for either the next tag, the next - # openning code span marker, or the next escaped character. - # Each token is then passed to handleSpanToken. - # - $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); - - # Create token from text preceding tag. - if ($parts[0] != "") { - $output .= $parts[0]; - } - - # Check if we reach the end. - if (isset($parts[1])) { - $output .= $this->handleSpanToken($parts[1], $parts[2]); - $str = $parts[2]; - } - else { - break; - } - } - - return $output; - } - - - protected function handleSpanToken($token, &$str) { - # - # Handle $token provided by parseSpan by determining its nature and - # returning the corresponding value that should replace it. - # - switch ($token{0}) { - case "\\": - return $this->hashPart("&#". ord($token{1}). ";"); - case "`": - # Search for end marker in remaining text. - if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', - $str, $matches)) - { - $str = $matches[2]; - $codespan = $this->makeCodeSpan($matches[1]); - return $this->hashPart($codespan); - } - return $token; // return as text since no ending marker found. - default: - return $this->hashPart($token); - } - } - - - protected function outdent($text) { - # - # Remove one level of line-leading tabs or spaces - # - return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); - } - - - # String length function for detab. `_initDetab` will create a function to - # hanlde UTF-8 if the default function does not exist. - protected $utf8_strlen = 'mb_strlen'; - - protected function detab($text) { - # - # Replace tabs with the appropriate amount of space. - # - # For each line we separate the line in blocks delemited by - # tab characters. Then we reconstruct every line by adding the - # appropriate number of space between each blocks. - - $text = preg_replace_callback('/^.*\t.*$/m', - array(&$this, '_detab_callback'), $text); - - return $text; - } - protected function _detab_callback($matches) { - $line = $matches[0]; - $strlen = $this->utf8_strlen; # strlen function for UTF-8. - - # Split in blocks. - $blocks = explode("\t", $line); - # Add each blocks to the line. - $line = $blocks[0]; - unset($blocks[0]); # Do not add first block twice. - foreach ($blocks as $block) { - # Calculate amount of space, insert spaces, insert block. - $amount = $this->tab_width - - $strlen($line, 'UTF-8') % $this->tab_width; - $line .= str_repeat(" ", $amount) . $block; - } - return $line; - } - protected function _initDetab() { - # - # Check for the availability of the function in the `utf8_strlen` property - # (initially `mb_strlen`). If the function is not available, create a - # function that will loosely count the number of UTF-8 characters with a - # regular expression. - # - if (function_exists($this->utf8_strlen)) return; - $this->utf8_strlen = create_function('$text', 'return preg_match_all( - "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", - $text, $m);'); - } - - - protected function unhash($text) { - # - # Swap back in all the tags hashed by _HashHTMLBlocks. - # - return preg_replace_callback('/(.)\x1A[0-9]+\1/', - array(&$this, '_unhash_callback'), $text); - } - protected function _unhash_callback($matches) { - return $this->html_hashes[$matches[0]]; - } - -} diff --git a/Library/Org/Parser/Driver/Ubb.php b/Library/Org/Parser/Driver/Ubb.php deleted file mode 100644 index a4f1dede..00000000 --- a/Library/Org/Parser/Driver/Ubb.php +++ /dev/null @@ -1,291 +0,0 @@ - -// +---------------------------------------------------------------------- -// | Ubb.php 2013-04-03 -// +---------------------------------------------------------------------- - -namespace Org\Parser\Driver; - -class Ubb{ - /** - * UBB标签匹配规则 - * @var array - */ - private $ubb = [ - ['table' , '\[table(?:=([\d%]*))?\]', '\[\/table\]', 'width'], - ['tr' , '\[tr\]', '\[\/tr\]', 'tag'], - ['th' , '\[th(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/th\]', 'widthAndHeight'], - ['td' , '\[td(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/td\]', 'widthAndHeight'], - ['img' , '\[img(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/img\]', 'imgWidthAndHeight'], - ['img' , '\[img=(.*?)(?:,([\d%]*)(?:,([\d%]*))?)?\/\]', 'img'], - ['a' , '\[url(?:=(.*?)(?:,([\w\-]*))?)?\]', '\[\/url\]', 'urlClass'], - ['a' , '\[a(?:=(.*?)(?:,([\w\-]*))?)?\]', '\[\/a\]', 'urlClass'], - ['a' , '\[url=(.*?)(?:,([\w\-]*))?\/\]', 'url'], - ['a' , '\[a=(.*?)(?:,([\w\-]*))?\/\]', 'url'], - ['a' , '\[email(?:=([\w\-]*))?\]', '\[\/email\]', 'emailClass'], - ['ul' , '\[ul(?:=([\w\-]*))?\]', '\[\/ul\]', 'class'], - ['ol' , '\[ol(?:=([\w\-]*))?\]', '\[\/ol\]', 'class'], - ['li' , '\[li(?:=([\w\-]*))?\]', '\[\/li\]', 'class'], - ['span' , '\[span(?:=([\w\-]*))?\]', '\[\/span\]', 'class'], - ['div' , '\[div(?:=([\w\-]*))?\]', '\[\/div\]', 'class'], - ['p' , '\[p(?:=([\w\-]*))?\]', '\[\/p\]', 'class'], - ['strong' , '\[b\]', '\[\/b\]', 'tag'], - ['strong' , '\[strong\]', '\[\/strong\]', 'tag'], - ['i' , '\[i\]', '\[\/i\]', 'tag'], - ['em' , '\[em\]', '\[\/em\]', 'tag'], - ['sub' , '\[sub\]', '\[\/sub\]', 'tag'], - ['sup' , '\[sup\]', '\[\/sup\]', 'tag'], - ['pre' , '\[code(?:=([a-z#\+\/]*))?\]', '\[\/code\]', 'code'], - ['code' , '\[line(?:=([a-z#\+\/]*))?\]', '\[\/line\]', 'code'], - ]; - - /** - * 解析UBB代码为HTML - * @param string $content 要解析的UBB代码 - * @return string 解析后的HTML代码 - */ - public function parse($content = ''){ - if(empty($content)) return ''; - - for($i = 0, $count = count($this->ubb); $i < $count; $i++){ - if(count($this->ubb[$i]) == 4){ //解析闭合标签 - $content = $this->closeTag($content, $this->ubb[$i]); - } else { - $content = $this->onceTag($content, $this->ubb[$i]); - } - } - - return nl2br($content); - } - - /** - * 解析闭合标签,支持嵌套 - * @param string $data 要解析的数据 - * @param array $rule 解析规则 - * @return string 解析后的内容 - */ - private function closeTag($data, $rule = ''){ - static $tag, $reg, $func, $count = 0; - if(is_string($data)){ - list($tag, $reg[0], $reg[1], $func) = $rule; - do{ - $data = preg_replace_callback("/({$reg[0]})(.*?)({$reg[1]})/is", - [$this, 'closeTag'], $data); - } while ($count && $count--); //递归解析,直到嵌套解析完毕 - return $data; - } elseif(is_array($data)){ - $num = count($data); - if(preg_match("/{$reg[0]}/is", $data[$num-2])){ //存在嵌套,进一步解析 - $count = 1; - $data[$num-2] = preg_replace_callback("/({$reg[0]})(.*?)({$reg[1]})/is", - [$this, 'closeTag'], $data[$num-2] . $data[$num-1]); - return $data[1] . $data[$num-2]; - } else { //不存在嵌套,直接解析内容 - $parse = '_' . $func; - $data[$num-2] = trim($data[$num-2], "\r\n"); //去掉标签内容两端的换行符 - return $this->$parse($tag, $data); - } - } - } - - /** - * 解析单标签 - * @param string $data 要解析的数据 - * @param array $rule 解析规则 - * @return string 解析后的内容 - */ - private function onceTag($data, $rule = ''){ - list($tag, $reg, $func) = $rule; - return preg_replace_callback("/{$reg}/is", [$this, '_' . $func], $data); - } - - /** - * 解析img单标签 - * @param array $data 解析数据 - * @return string 解析后的标签 - */ - private function _img($data){ - $data[4] = $data[1]; - return $this->_imgWidthAndHeight('', $data); - } - - /** - * 解析url单标签 - * @param array $data 解析数据 - * @return string 解析后的标签 - */ - private function _url($data){ - $data[3] = $data[2]; - $data[4] = $data[2] = $data[1]; - return $this->_urlClass('', $data); - } - - /** - * 解析没有属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - 标签内容 - * @return string 解析后的标签 - */ - private function _tag($name, $data){ - return "<{$name}>{$data[2]}"; - } - - /** - * 解析代码 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - 语言类型,[3] - 代码内容 - * @return string 解析后的标签 - */ - private function _code($name, $data){ - $fix = ($name == 'pre') ? ['
    ', '
    '] : ['', '']; - if(empty($data[2])){ - $data = "{$fix[0]}{$data[3]}{$fix[1]}"; - } else { - $data = "{$fix[0]}{$data[3]}{$fix[1]}"; - } - return $data; - } - - /** - * 解析含有width属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - width, [3] - 标签内容 - * @return string 解析后的标签 - */ - private function _width($name, $data){ - if(empty($data[2])){ - $data = "<{$name}>{$data[3]}"; - } else { - $data = "<{$name} width=\"{$data[2]}\">{$data[3]}"; - } - return $data; - } - - /** - * 解析含有width和height属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - width, [3] - height, [4] - 标签内容 - * @return string 解析后的标签 - */ - private function _widthAndHeight($name, $data){ - if(empty($data[2]) && empty($data[3])){ - $data = "<{$name}>{$data[4]}"; - } elseif(!empty($data[2]) && empty($data[3])) { - $data = "<{$name} width=\"{$data[2]}\">{$data[4]}"; - } elseif(empty($data[2]) && !empty($data[3])) { - $data = "<{$name} height=\"{$data[3]}\">{$data[4]}"; - } else { - $data = "<{$name} width=\"{$data[2]}\" height=\"{$data[3]}\">{$data[4]}"; - } - return $data; - } - - /** - * 解析含有width和height属性的图片标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - width, [3] - height, [4] - 图片URL - * @return string 解析后的标签 - */ - private function _imgWidthAndHeight($name, $data){ - if(empty($data[2]) && empty($data[3])){ - $data = ""; - } elseif(!empty($data[2]) && empty($data[3])) { - $data = ""; - } elseif(empty($data[2]) && !empty($data[3])) { - $data = ""; - } else { - $data = ""; - } - return $data; - } - - /** - * 解析含有class属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - class, [3] - 标签内容 - * @return string 解析后的标签 - */ - private function _class($name, $data){ - if(empty($data[2])){ - $data = "<{$name}>{$data[3]}"; - } else { - $data = "<{$name} class=\"{$data[2]}\">{$data[3]}"; - } - return $data; - } - - /** - * 解析含有class属性的url标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - url, [3] - text - * @return string 解析后的标签 - */ - private function _urlClass($name, $data){ - empty($data[2]) && $data[2] = $data[4]; - if(empty($data[3])){ - $data = "{$data[4]}"; - } else { - $data = "{$data[4]}"; - } - return $data; - } - - /** - * 解析含有class属性的email标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - class, [3] - email地址 - * @return string 解析后的标签 - */ - private function _emailClass($name, $data){ - //不是正确的EMAIL则不解析 - if(preg_match('/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', $data[3])) - return $data[0]; - - //编码email地址,防治被采集 - $email = $this->encodeEmailAddress($data[3]); - - if(empty($data[2])){ - $data = "{$email[1]}"; - } else { - $data = "{$email[1]}"; - } - return $data; - } - - /** - * 编码EMAIL地址,可以防治部分采集软件 - * @param string $addr EMAIL地址 - * @return array 编码后的EMAIL地址 [0] - 带mailto, [1] - 不带mailto - */ - private function encodeEmailAddress($addr) { - $addr = "mailto:" . $addr; - $chars = preg_split('/(? $char) { - $ord = ord($char); - # Ignore non-ascii chars. - if ($ord < 128) { - $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. - # roughly 10% raw, 45% hex, 45% dec - # '@' *must* be encoded. I insist. - if ($r > 90 && $char != '@') /* do nothing */; - else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; - else $chars[$key] = '&#'.$ord.';'; - } - } - - $addr = implode('', $chars); - $text = implode('', array_slice($chars, 7)); # text without `mailto:` - - return [$addr, $text]; - } - -} diff --git a/Library/Org/Upload.php b/Library/Org/Upload.php deleted file mode 100644 index 16e35d60..00000000 --- a/Library/Org/Upload.php +++ /dev/null @@ -1,515 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Org; - -class Upload { - protected $config = [ - 'max_size' => -1, // 上传文件的最大值 - 'support_multi' => true, // 是否支持多文件上传 - 'allow_exts' => [], // 允许上传的文件后缀 留空不作后缀检查 - 'allow_types' => [], // 允许上传的文件类型 留空不做检查 - 'thumb' => false, // 使用对上传图片进行缩略图处理 - 'thumb_max_width' => '',// 缩略图最大宽度 - 'thumb_max_height' => '',// 缩略图最大高度 - 'thumb_prefix' => 'thumb_',// 缩略图前缀 - 'thumb_suffix' => '', - 'thumb_path' => '',// 缩略图保存路径 - 'thumb_file' => '',// 缩略图文件名 - 'thumb_ext' => '',// 缩略图扩展名 - 'thumb_remove_origin' => false,// 是否移除原图 - 'zip_images' => false,// 压缩图片文件上传 - 'auto_sub' => false,// 启用子目录保存文件 - 'sub_type' => 'hash',// 子目录创建方式 可以使用hash date custom - 'sub_dir' => '', // 子目录名称 subType为custom方式后有效 - 'date_format' => 'Ymd', - 'hash_level' => 1, // hash的目录层次 - 'save_path' => '',// 上传文件保存路径 - 'auto_check' => true, // 是否自动检查附件 - 'upload_replace' => false,// 存在同名是否覆盖 - 'save_rule' => 'uniqid',// 上传文件命名规则 - 'hash_type' => 'md5_file',// 上传文件Hash规则函数名 - ]; - - // 错误信息 - private $error = ''; - // 上传成功的文件信息 - private $uploadFileInfo ; - - public function __get($name){ - if(isset($this->config[$name])) { - return $this->config[$name]; - } - return null; - } - - public function __set($name,$value){ - if(isset($this->config[$name])) { - $this->config[$name] = $value; - } - } - - public function __isset($name){ - return isset($this->config[$name]); - } - - /** - * 架构函数 - * @access public - * @param array $config 上传参数 - */ - public function __construct($config=[]) { - if(is_array($config)) { - $this->config = array_merge($this->config,$config); - } - } - - /** - * 上传一个文件 - * @access protected - * @param mixed $name 数据 - * @param string $value 数据表名 - * @return string - */ - protected function save($file) { - $filename = $file['save_path'].$file['savename']; - if(!$this->upload_replace && is_file($filename)) { - // 不覆盖同名文件 - $this->error = '文件已经存在!'.$filename; - return false; - } - // 如果是图像文件 检测文件格式 - if( in_array(strtolower($file['extension']),['gif','jpg','jpeg','bmp','png','swf'])) { - $info = getimagesize($file['tmp_name']); - if(false === $info || ('gif' == strtolower($file['extension']) && empty($info['bits']))){ - $this->error = '非法图像文件'; - return false; - } - } - if(!move_uploaded_file($file['tmp_name'], $this->autoCharset($filename,'utf-8','gbk'))) { - $this->error = '文件上传保存错误!'; - return false; - } - if($this->thumb && in_array(strtolower($file['extension']),['gif','jpg','jpeg','bmp','png'])) { - $image = getimagesize($filename); - if(false !== $image) { - //是图像文件生成缩略图 - $thumbWidth = explode(',',$this->thumb_max_width); - $thumbHeight = explode(',',$this->thumb_max_height); - $thumb_prefix = explode(',',$this->thumb_prefix); - $thumb_suffix = explode(',',$this->thumb_suffix); - $thumb_file = explode(',',$this->thumb_file); - $thumb_path = $this->thumb_path?$this->thumb_path:dirname($filename).'/'; - $thumb_ext = $this->thumb_ext ? $this->thumb_ext : $file['extension']; //自定义缩略图扩展名 - // 生成图像缩略图 - for($i=0,$len=count($thumbWidth); $i<$len; $i++) { - if(!empty($thumb_file[$i])) { - $thumbname = $thumb_file[$i]; - }else{ - $prefix = isset($thumb_prefix[$i])?$thumb_prefix[$i]:$thumb_prefix[0]; - $suffix = isset($thumb_suffix[$i])?$thumb_suffix[$i]:$thumb_suffix[0]; - $thumbname = $prefix.basename($filename,'.'.$file['extension']).$suffix; - } - ThinkImage::thumb($filename,$thumb_path.$thumbname.'.'.$thumb_ext,'',$thumbWidth[$i],$thumbHeight[$i],true); - } - if($this->thumb_remove_origin) { - // 生成缩略图之后删除原图 - unlink($filename); - } - } - } - if($this->zipImags) { - // TODO 对图片压缩包在线解压 - - } - return true; - } - - /** - * 上传所有文件 - * @access public - * @param string $savePath 上传文件保存路径 - * @return string - */ - public function upload($savePath ='') { - //如果不指定保存文件名,则由系统默认 - if(empty($savePath)) - $savePath = $this->save_path; - // 检查上传目录 - if(!is_dir($savePath)) { - // 检查目录是否编码后的 - if(is_dir(base64_decode($savePath))) { - $savePath = base64_decode($savePath); - }else{ - // 尝试创建目录 - if(!mkdir($savePath)){ - $this->error = '上传目录'.$savePath.'不存在'; - return false; - } - } - }else { - if(!is_writeable($savePath)) { - $this->error = '上传目录'.$savePath.'不可写'; - return false; - } - } - $fileInfo = []; - $isUpload = false; - - // 获取上传的文件信息 - // 对$_FILES数组信息处理 - $files = $this->dealFiles($_FILES); - foreach($files as $key => $file) { - //过滤无效的上传 - if(!empty($file['name'])) { - //登记上传文件的扩展信息 - if(!isset($file['key'])) $file['key'] = $key; - $file['extension'] = $this->getExt($file['name']); - $file['savepath'] = $savePath; - $file['savename'] = $this->getSaveName($file); - - // 自动检查附件 - if($this->auto_check) { - if(!$this->check($file)) - return false; - } - - //保存上传文件 - if(!$this->save($file)) return false; - if(function_exists($this->hash_type)) { - $fun = $this->hash_type; - $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk')); - } - //上传成功后保存文件信息,供其他地方调用 - unset($file['tmp_name'],$file['error']); - $fileInfo[] = $file; - $isUpload = true; - } - } - if($isUpload) { - $this->uploadFileInfo = $fileInfo; - return true; - }else { - $this->error = '没有选择上传文件'; - return false; - } - } - - /** - * 上传单个上传字段中的文件 支持多附件 - * @access public - * @param array $file 上传文件信息 - * @param string $savePath 上传文件保存路径 - * @return string - */ - public function uploadOne($file,$savePath=''){ - //如果不指定保存文件名,则由系统默认 - if(empty($savePath)) - $savePath = $this->save_path; - // 检查上传目录 - if(!is_dir($savePath)) { - // 尝试创建目录 - if(!mkdir($savePath,0777,true)){ - $this->error = '上传目录'.$savePath.'不存在'; - return false; - } - }else { - if(!is_writeable($savePath)) { - $this->error = '上传目录'.$savePath.'不可写'; - return false; - } - } - //过滤无效的上传 - if(!empty($file['name'])) { - $fileArray = []; - if(is_array($file['name'])) { - $keys = array_keys($file); - $count = count($file['name']); - for ($i=0; $i<$count; $i++) { - foreach ($keys as $key) - $fileArray[$i][$key] = $file[$key][$i]; - } - }else{ - $fileArray[] = $file; - } - $info = []; - foreach ($fileArray as $key=>$file){ - //登记上传文件的扩展信息 - $file['extension'] = $this->getExt($file['name']); - $file['savepath'] = $savePath; - $file['savename'] = $this->getSaveName($file); - // 自动检查附件 - if($this->auto_check) { - if(!$this->check($file)) - return false; - } - //保存上传文件 - if(!$this->save($file)) return false; - if(function_exists($this->hash_type)) { - $fun = $this->hash_type; - $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk')); - } - unset($file['tmp_name'],$file['error']); - $info[] = $file; - } - // 返回上传的文件信息 - return $info; - }else { - $this->error = '没有选择上传文件'; - return false; - } - } - - /** - * 转换上传文件数组变量为正确的方式 - * @access protected - * @param array $files 上传的文件变量 - * @return array - */ - protected function dealFiles($files) { - $fileArray = []; - $n = 0; - foreach ($files as $key=>$file){ - if(is_array($file['name'])) { - $keys = array_keys($file); - $count = count($file['name']); - for ($i=0; $i<$count; $i++) { - $fileArray[$n]['key'] = $key; - foreach ($keys as $_key){ - $fileArray[$n][$_key] = $file[$_key][$i]; - } - $n++; - } - }else{ - $fileArray[$key] = $file; - } - } - return $fileArray; - } - - /** - * 获取错误代码信息 - * @access public - * @param string $errorNo 错误号码 - * @return void - */ - protected function error($errorNo) { - switch($errorNo) { - case 1: - $this->error = '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值'; - break; - case 2: - $this->error = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值'; - break; - case 3: - $this->error = '文件只有部分被上传'; - break; - case 4: - $this->error = '没有文件被上传'; - break; - case 6: - $this->error = '找不到临时文件夹'; - break; - case 7: - $this->error = '文件写入失败'; - break; - default: - $this->error = '未知上传错误!'; - } - return ; - } - - /** - * 根据上传文件命名规则取得保存文件名 - * @access protected - * @param string $filename 数据 - * @return string - */ - protected function getSaveName($filename) { - $rule = $this->save_rule; - if(empty($rule)) {//没有定义命名规则,则保持文件名不变 - $saveName = $filename['name']; - }else { - if(function_exists($rule)) { - //使用函数生成一个唯一文件标识号 - $saveName = $rule().".".$filename['extension']; - }else { - //使用给定的文件名作为标识号 - $saveName = $rule.".".$filename['extension']; - } - } - if($this->auto_sub) { - // 使用子目录保存文件 - $filename['savename'] = $saveName; - $saveName = $this->getSubName($filename).$saveName; - } - return $saveName; - } - - /** - * 获取子目录的名称 - * @access protected - * @param array $file 上传的文件信息 - * @return string - */ - protected function getSubName($file) { - switch($this->sub_type) { - case 'custom': - $dir = $this->sub_dir; - break; - case 'date': - $dir = date($this->date_format,time()).'/'; - break; - case 'hash': - default: - $name = md5($file['savename']); - $dir = ''; - for($i=0;$i<$this->hash_level;$i++) { - $dir .= $name{$i}.'/'; - } - break; - } - if(!is_dir($file['savepath'].$dir)) { - mkdir($file['savepath'].$dir,0777,true); - } - return $dir; - } - - /** - * 检查上传的文件 - * @access protected - * @param array $file 文件信息 - * @return boolean - */ - protected function check($file) { - if($file['error']!== 0) { - //文件上传失败 - //捕获错误代码 - $this->error($file['error']); - return false; - } - //文件上传成功,进行自定义规则检查 - //检查文件大小 - if(!$this->checkSize($file['size'])) { - $this->error = '上传文件大小不符!'; - return false; - } - - //检查文件Mime类型 - if(!$this->checkType($file['type'])) { - $this->error = '上传文件MIME类型不允许!'; - return false; - } - //检查文件类型 - if(!$this->checkExt($file['extension'])) { - $this->error ='上传文件类型不允许'; - return false; - } - - //检查是否合法上传 - if(!$this->checkUpload($file['tmp_name'])) { - $this->error = '非法上传文件!'; - return false; - } - return true; - } - - // 自动转换字符集 支持数组转换 - protected function autoCharset($fContents, $from='gbk', $to='utf-8') { - $from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from; - $to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to; - if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) { - //如果编码相同或者非字符串标量则不转换 - return $fContents; - } - if (function_exists('mb_convert_encoding')) { - return mb_convert_encoding($fContents, $to, $from); - } elseif (function_exists('iconv')) { - return iconv($from, $to, $fContents); - } else { - return $fContents; - } - } - - /** - * 检查上传的文件类型是否合法 - * @access protected - * @param string $type 数据 - * @return boolean - */ - protected function checkType($type) { - if(!empty($this->allow_types)) - return in_array(strtolower($type),$this->allow_types); - return true; - } - - - /** - * 检查上传的文件后缀是否合法 - * @access protected - * @param string $ext 后缀名 - * @return boolean - */ - protected function checkExt($ext) { - if(!empty($this->allow_exts)) - return in_array(strtolower($ext),$this->allow_exts,true); - return true; - } - - /** - * 检查文件大小是否合法 - * @access protected - * @param integer $size 数据 - * @return boolean - */ - protected function checkSize($size) { - return !($size > $this->max_size) || (-1 == $this->max_size); - } - - /** - * 检查文件是否非法提交 - * @access protected - * @param string $filename 文件名 - * @return boolean - */ - protected function checkUpload($filename) { - return is_uploaded_file($filename); - } - - /** - * 取得上传文件的后缀 - * @access protected - * @param string $filename 文件名 - * @return boolean - */ - protected function getExt($filename) { - $pathinfo = pathinfo($filename); - return $pathinfo['extension']; - } - - /** - * 取得上传文件的信息 - * @access public - * @return array - */ - public function getUploadFileInfo() { - return $this->uploadFileInfo; - } - - /** - * 取得最后一次错误信息 - * @access public - * @return string - */ - public function getErrorMsg() { - return $this->error; - } -} \ No newline at end of file