OSDN Git Service

NP_Paint v1.18
[nucleus-jp/nucleus-plugins.git] / trunk / NP_Paint / NP_Paint.php
diff --git a/trunk/NP_Paint/NP_Paint.php b/trunk/NP_Paint/NP_Paint.php
new file mode 100644 (file)
index 0000000..7f9ef16
--- /dev/null
@@ -0,0 +1,940 @@
+<?php\r
+// vim: tabstop=2:shiftwidth=2\r
+\r
+/**\r
+  * NP_Paint ($Revision: 1.273 $)\r
+  * by hsur ( http://blog.cles.jp/np_cles )\r
+  * \r
+  * $Id: NP_Paint.php,v 1.273 2010/06/06 11:44:19 hsur Exp $\r
+*/\r
+\r
+/*\r
+  * Copyright (C) 2005-2010 CLES. All rights reserved.\r
+  *\r
+  * This program is free software; you can redistribute it and/or\r
+  * modify it under the terms of the GNU General Public License\r
+  * as published by the Free Software Foundation; either version 2\r
+  * of the License, or (at your option) any later version.\r
+  * \r
+  * This program is distributed in the hope that it will be useful,\r
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+  * GNU General Public License for more details.\r
+  * \r
+  * You should have received a copy of the GNU General Public License\r
+  * along with this program; if not, write to the Free Software\r
+  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\r
+  * \r
+  * In addition, as a special exception, cles( http://blog.cles.jp/np_cles ) gives\r
+  * permission to link the code of this program with those files in the PEAR\r
+  * library that are licensed under the PHP License (or with modified versions\r
+  * of those files that use the same license as those files), and distribute\r
+  * linked combinations including the two. You must obey the GNU General Public\r
+  * License in all respects for all of the code used other than those files in\r
+  * the PEAR library that are licensed under the PHP License. If you modify\r
+  * this file, you may extend this exception to your version of the file,\r
+  * but you are not obligated to do so. If you do not wish to do so, delete\r
+  * this exception statement from your version.\r
+*/\r
+\r
+if (!class_exists('NucleusPlugin')) exit;\r
+define("NP_PAINT_IMAGE_NAME", "pbbsimage");\r
+define("NP_PAINT_TICKET_TABLE", "plugin_paint_tickets");\r
+define("NP_PAINT_TICKET_LIFETIME", 86400);\r
+\r
+global $DIR_LIBS;\r
+require_once($DIR_LIBS . 'MEDIA.php');\r
+\r
+// load class\r
+require_once(dirname(__FILE__).'/sharedlibs/sharedlibs.php');\r
+require_once('cles/Template.php');\r
+require_once(dirname(__FILE__).'/paint/PaintPlugin.php');\r
+\r
+class NP_Paint extends NucleusPlugin {\r
+\r
+       // name of plugin\r
+       function getName() {\r
+               return 'Paint';\r
+       }\r
+\r
+       // author of plugin\r
+       function getAuthor() {\r
+               return 'hsur';\r
+       }\r
+\r
+       // an URL to the plugin website\r
+       // can also be of the form mailto:foo@bar.com\r
+       function getURL() {\r
+               return 'http://blog.cles.jp/np_cles/category/31/subcatid/5';\r
+       }\r
+\r
+       // version of the plugin\r
+       function getVersion() {\r
+               return '1.18.0';\r
+       }\r
+       \r
+       function hasAdminArea() {\r
+               return 1;\r
+       }\r
+\r
+       function install() {\r
+               // FORM default\r
+               $this->createOption('defaultWidth', _PAINT_defaultWidth, 'text', '300', 'numerical=true');              \r
+               $this->createOption('defaultHeight', _PAINT_defaultHeight, 'text', '300', 'numerical=true');            \r
+               $this->createOption('defaultAnimation', _PAINT_defaultAnimation, 'yesno', 'yes');               \r
+               $this->createOption('defaultApplet', _PAINT_defaultApplet, 'select', '', '');\r
+               $this->createOption('defaultPalette', _PAINT_defaultPalette, 'select', '', '');\r
+\r
+               $this->createOption('defaultImgType', _PAINT_defaultImgType, 'select', 'AUTO', 'AUTO|AUTO|JPG|JPG|PNG|PNG');\r
+               $this->createOption('defaultImgCompress', _PAINT_defaultImgCompress, 'text', '15', 'numerical=true');           \r
+               $this->createOption('defaultImgDecrease', _PAINT_defaultImgDecrease, 'text', '60', 'numerical=true');           \r
+               $this->createOption('defaultImgQuality', _PAINT_defaultImgQuality, 'text', '75', 'numerical=true');             \r
+\r
+               $this->createOption('defaultAppletQuality', _PAINT_defaultAppletQuality, 'select', '1', '1|1|2|2|3|3|4|4|5|5');\r
+\r
+               $this->createOption('bodyTpl', _PAINT_bodyTpl, 'textarea', '<%paint(<%url%>|<%w%>|<%h%>|'.NP_PAINT_IMAGE_NAME.')%>');\r
+               $this->createOption('tagTpl', _PAINT_tagTpl, 'textarea', '<%img%><a href="<%viewer%>" onclick="window.open(this.href, \'popupwindow\', \'width=400, height=400, scrollbars, resizable\'); return false; " >'._PAINT_STAR.'Anime</a>');\r
+               $this->createOption('imageTpl', _PAINT_imageTpl, 'textarea', '<%image(<%url%>|<%w%>|<%h%>|<%alt%>)%><%continue%>');\r
+               $this->createOption('continueTpl', _PAINT_continueTpl, 'textarea', '<br /><a onclick="window.open(this.href, \'popupwindow\', \'width=400, height=400, scrollbars, resizable\'); return false;" href="<%actionurl%>">'._PAINT_STAR.'Continue</a>');\r
+               // debug\r
+               $this->createOption('debug', _PAINT_debug, 'yesno', 'no');\r
+               \r
+               // for authentication\r
+               sql_query("\r
+                       CREATE TABLE IF NOT EXISTS \r
+                       ".sql_table(NP_PAINT_TICKET_TABLE).'\r
+                       (\r
+                               `ticket` CHAR(40) NOT NULL,\r
+                               `member` INT(11) NOT NULL,\r
+                               `generated` TIMESTAMP,\r
+                               PRIMARY KEY (`ticket`, `member`),\r
+                               INDEX genarated_idx (`generated` DESC)\r
+                       )\r
+               ');\r
+       }\r
+       \r
+       function unInstall() {\r
+               sql_query("DROP TABLE ".sql_table(NP_PAINT_TICKET_TABLE));\r
+       }\r
+       \r
+       function getMinNucleusVersion() { return 330; }\r
+       function getMinNucleusPatchLevel() { return 0; }\r
+\r
+       // a description to be shown on the installed plugins listing\r
+       function getDescription() {\r
+               return '[$Revision: 1.273 $]<br />' . _PAINT_DESCRIPTION;\r
+       }\r
+\r
+       function supportsFeature($what) {\r
+               switch ($what) {\r
+                       case 'SqlTablePrefix' :\r
+//                     case 'HelpPage':\r
+                               return 1;\r
+                       default :\r
+                               return 0;\r
+               }\r
+       }\r
+       \r
+       function getEventList() {\r
+               return array('PrePluginOptionsEdit', 'PreItem');\r
+       }\r
+       \r
+       function event_PrePluginOptionsEdit(&$data) {\r
+               $this->_loadPlugin();\r
+               $trimChar = array(\r
+                       '=' => '',\r
+                       '|' => '',\r
+                       ';' => '',\r
+               );\r
+\r
+               switch($data['context']){\r
+                       case 'global':\r
+                               if( $data['plugid'] != $this->getID() ) return ;\r
+                               \r
+                               $appletTypeinfo = '';\r
+                               foreach($this->applets as $key => $applet){\r
+                                       if($appletTypeinfo) $appletTypeinfo .= '|';\r
+                                       $applet->name = strtr($applet->name, $trimChar);\r
+                                       $key = strtr($key, $trimChar);\r
+                                       $appletTypeinfo .= "{$applet->name}|{$key}";\r
+                               }\r
+                               $paletteTypeinfo = '';\r
+                               foreach($this->palettes as $key => $palette){\r
+                                       if($paletteTypeinfo) $paletteTypeinfo .= '|';\r
+                                       $palette->name = strtr($palette->name, $trimChar);\r
+                                       $key = strtr($key, $trimChar);\r
+                                       $paletteTypeinfo .= "{$palette->name}|{$key}";\r
+                               }\r
+                               foreach($data['options'] as $oid => $option ){\r
+                                       switch($data['options'][$oid]['name']){\r
+                                               case 'defaultApplet':\r
+                                                       $data['options'][$oid]['typeinfo'] = $appletTypeinfo;\r
+                                                       break;\r
+                                               case 'defaultPalette':\r
+                                                       $data['options'][$oid]['typeinfo'] = $paletteTypeinfo;\r
+                                                       break;\r
+                                       }\r
+                               }\r
+                                                               \r
+                               break;\r
+                       default:\r
+                               // nothing      \r
+               }\r
+       }\r
+\r
+/*\r
+       function doItemVar($item, $arg){\r
+               $arr[1] = $arg;\r
+               echo $this->_convertPaint($arr);\r
+       }\r
+*/\r
+\r
+       function event_PreItem($data) {\r
+               $this->_loadPlugin();\r
+               $preg_expr = "#<\%paint\((.*?)\)%\>#i";\r
+               $this->currentItem = &$data["item"];\r
+               \r
+               $this->currentItem->body = preg_replace_callback($preg_expr, array(&$this, '_convertPaint'), $this->currentItem->body);\r
+               $this->currentItem->more = preg_replace_callback($preg_expr, array(&$this, '_convertPaint'), $this->currentItem->more);\r
+       }\r
+       \r
+       function _convertPaint($matches) {\r
+               global $CONF, $DIR_MEDIA, $member;\r
+               list($url, $w, $h, $alt) = explode("|", $matches[1], 4);\r
+               \r
+               if (strstr($url,'/'))\r
+                       $collection = intval(dirname($url));\r
+               else\r
+                       $collection = intval($this->currentItem->authorid);\r
+                       \r
+               $vars = array (\r
+                       'w' => intval($w),\r
+                       'h' => intval($h),\r
+                       'url' => $url,\r
+                       'alt' => $alt,\r
+               );\r
+               \r
+               $basename = basename($url, '.jpg');\r
+               $basename = basename($basename, '.png');\r
+               foreach( $this->viewers as $key => $viewer ){\r
+                       foreach( $viewer->animeExt as $ext  ){\r
+                               $file = $DIR_MEDIA . $collection . '/' . $basename . '.' . $ext;\r
+                               if( file_exists( $file ) ){\r
+                                       $vars['viewer'] = htmlspecialchars($CONF['ActionURL'] . "?action=plugin&name=Paint&type=viewer&w=".$vars['w']."&h=".$vars['h']."&file={$collection}/{$basename}.{$ext}&viewer=$key", ENT_QUOTES);\r
+                                       break 2;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               if ( $member->isLoggedIn() && $member->getID() == $collection && $this->viewers['continue'] ){\r
+                       $vars['actionurl'] = htmlspecialchars($CONF['ActionURL'] . "?action=plugin&name=Paint&type=viewer&w=".$vars['w']."&h=".$vars['h']."&file=".$url."&viewer=continue", ENT_QUOTES);\r
+                       $vars['continue'] = TEMPLATE :: fill($this->getOption('continueTpl'), $vars);\r
+               }\r
+               \r
+               $vars['img'] = TEMPLATE :: fill($this->getOption('imageTpl'), $vars);\r
+               \r
+               if( $vars['viewer'] )\r
+                       return TEMPLATE :: fill($this->getOption('tagTpl'), $vars);                     \r
+               return $vars['img'];\r
+       }\r
+                       \r
+       function init(){\r
+               $this->template =& new cles_Template(dirname(__FILE__).'/paint/template');\r
+               \r
+               $this->parsers = Array();\r
+               $this->applets = Array();\r
+               $this->palettes = Array();\r
+               $this->viewers = Array();\r
+               $this->files = Array();\r
+               $this->disabledPlugin = Array();\r
+               $this->isPluginLoaded = false;\r
+               \r
+               // include language file for this plugin \r
+               $language = ereg_replace( '[\\|/]', '', getLanguageName()); \r
+               if (file_exists($this->getDirectory().'language/'.$language.'.php')) \r
+                       @ include_once($this->getDirectory().'language/'.$language.'.php');\r
+       }\r
+               \r
+       function doAction($type) {\r
+               @ini_set('display_errors', 0);\r
+               //@ini_set('error_reporting', 0);\r
+               \r
+               global $member;\r
+               $this->_loadPlugin();\r
+               header('Pragma: no-cache');\r
+               header('Expires: 0');\r
+               \r
+               switch ($type) {\r
+                       case 'postimg':\r
+                               $err = $this->_postimg(requestVar('parser'));\r
+                               \r
+                               if($err){\r
+                                       $this->_warn('postimg Err: ' . $err);\r
+                                       $file = $line = '';\r
+                                       if( ! headers_sent($file, $line) ){\r
+                                               header("HTTP/1.0 500 Internal Server Error");\r
+                                               header("Status: 500 Internal Server Error");\r
+                                               echo 'postimg Err: ' . mb_convert_encoding($err, 'UTF-8', _CHARSET);\r
+                                       } else {\r
+                                               $this->_warn(_PAINT_HeadersAlreadySent . "file:$file, line:$line" );\r
+                                               echo "error\n" . mb_convert_encoding($err, "UTF-8", _CHARSET);\r
+                                       }\r
+                               }\r
+                               // always no err\r
+                               return '';\r
+                               break;\r
+\r
+                       case 'applet':\r
+                               if ( ! $member->isLoggedIn() )\r
+                                       return _PAINT_NeedLogin;\r
+                               return $this->_showApplet();\r
+                               break;\r
+                               \r
+                       case 'postsuccess':\r
+                               if ( ! $member->isLoggedIn() )\r
+                                       return _PAINT_NeedLogin;\r
+                               \r
+                               if( intRequestVar('ow') ){\r
+                                       $this->_showOk();\r
+                                       return '';\r
+                               }\r
+                               \r
+                               return $this->_showItemAddForm();\r
+                               break;\r
+                       \r
+                       case 'viewer':\r
+                               return $this->_showViewer();\r
+                               break;\r
+\r
+                       case 'plugin':\r
+                               echo 'NP_Paint: ' . $this->getVersion() . ' ($Id: NP_Paint.php,v 1.273 2010/06/06 11:44:19 hsur Exp $)<br />';\r
+                               foreach( $this->parsers as $key => $name){\r
+                                       echo 'Parser: ' . $key . ' (' . $name->id .  ')<br />';\r
+                               }\r
+                               foreach( $this->applets as $key => $name){\r
+                                       echo 'Applet: ' . $key . ' (' . $name->id .  ')<br />';\r
+                               }\r
+                               foreach( $this->palettes as $key => $name){\r
+                                       echo 'Palette: ' . $key . ' (' . $name->id .  ')<br />';\r
+                               }\r
+                               foreach( $this->viewers as $key => $name){\r
+                                       echo 'Viewer: ' . $key . ' (' . $name->id .  ')<br />';\r
+                               }\r
+                               return '';\r
+                               break;\r
+                               \r
+                       case 'getLoginkey':\r
+                               if ( $member->isLoggedIn() ){\r
+                                       header('Content-Type: application/xml');\r
+                                       echo $this->_getLoginkey();\r
+                               } else {\r
+                                       header("HTTP/1.0 500 Internal Server Error");\r
+                                       header("Status: 500 Internal Server Error");\r
+                                       echo _PAINT_NeedLogin;\r
+                               }\r
+                               return '';\r
+                               break;\r
+                       \r
+                       // other actions result in an error\r
+                       case '':\r
+                       default:\r
+                               return 'Unexisting action: ' . $type;\r
+               }\r
+       }\r
+       \r
+       function doSkinVar($skinType, $type = '') {\r
+               global $member, $CONF;\r
+               \r
+               if($mes = $this->_phpVersionWarning() ){\r
+                       echo $mes;\r
+                       $this->_warn($mes);\r
+               }\r
+               \r
+               switch ($type) {\r
+                       case '' :\r
+                       case 'form' :\r
+                               if ( $member->isLoggedIn() ){\r
+                                       $this->_loadPlugin();\r
+                                       $vars = array (\r
+                                               'ActionURL' => $CONF['ActionURL'],\r
+                                               'appletSelect' => $this->_getAppletSelect(),\r
+                                               'paletteSelect' => $this->_getPaletteSelect(),\r
+                                               'paletteSelectExtra' => $this->_getPaletteSelectExtra(),\r
+                                               'qualitySelect' => $this->_getQualitySelect(),\r
+                                               'animation' => ($this->getOption('defaultAnimation') == 'yes') ? 'checked="checked"' : '',\r
+                                               'defaultWidth' => $this->getOption('defaultWidth'),\r
+                                               'defaultHeight' => $this->getOption('defaultHeight'),\r
+                                       );\r
+                                       $tpl = $this->template->fetch('form', strtolower(__CLASS__));\r
+                                       echo $this->template->fill($tpl, $vars, false);\r
+                               } else { \r
+                                       echo '<span class="paint">Powered by <a href="http://blog.cles.jp/">NP_Paint</a></span>';\r
+                               }\r
+                               break;\r
+               }\r
+       }\r
+\r
+       function _phpVersionWarning(){\r
+               $required = '4.3.2';\r
+               if( ! version_compare(phpversion() , $required , '>=') ){\r
+                       return 'Warning' . _PAINT_phpVersion_before . $required . _PAINT_phpVersion_after ;\r
+               }\r
+               return '';\r
+       }\r
+       \r
+       function _showApplet(){\r
+               global $DIR_MEDIA, $CONF, $member;\r
+\r
+               $w = intRequestVar('w') ? intRequestVar('w') : $this->getOption('defaultWidth');\r
+               $h = intRequestVar('h') ? intRequestVar('h') : $this->getOption('defaultHeight');\r
+               $animation = intRequestVar('animation') ? true : false;\r
+               $ow = intRequestVar('ow');\r
+               $usePch = intRequestVar('usepch') ? true : false;\r
+               $file = requestVar('file');\r
+               $quality = intRequestVar('quality') ? intRequestVar('quality') : 1 ;\r
+               \r
+               if( $file ){\r
+                       $collection = intval(dirname($file));\r
+                       if( $collection != intval($member->getID()) ){\r
+                               $file = null;\r
+                               $this->_warn( _PAINT_illegalCollection );\r
+                       }\r
+               }\r
+               \r
+               $applet =& $this->applets[requestVar('applet')];\r
+               if(! $applet ){\r
+                       $this->_warn(_PAINT_canNotFindApplet);\r
+                       return _PAINT_canNotFindApplet;\r
+               }\r
+               $palette =& $this->palettes[requestVar('palette')];\r
+               \r
+               $header = $beforeapplet = $param = $afterapplet = $copyright = '';\r
+               \r
+               if($applet){\r
+                       $header .= $applet->getHeaderPart();    \r
+                       $beforeapplet .= $applet->getBeforeAppletPart();\r
+                       $param .= $applet->getParamPart();\r
+                       $afterapplet .= $applet->getAfterAppletPart();\r
+                       $copyright .= $applet->getCopyrightsPart();\r
+               }\r
+\r
+               if($palette){\r
+                       $header .= $palette->getHeaderPart();   \r
+                       $beforeapplet .= $palette->getBeforeAppletPart();\r
+                       $param .= $palette->getParamPart();\r
+                       $afterapplet .= $palette->getAfterAppletPart();\r
+                       $copyright .= $palette->getCopyrightsPart();\r
+               }\r
+                               \r
+               if( $animation ){\r
+                       $param .= '<param name="thumbnail_type" value="animation" />';\r
+               }\r
+               \r
+               $copyright .= 'NP_Paint by <a href="http://blog.cles.jp">cles</a><br />';\r
+               \r
+               if( $file && file_exists( $DIR_MEDIA . $file ) ){\r
+                       $appletName = requestVar('applet');\r
+                       list($animePath, $appletName) = $this->findAppletByImg($file);\r
+                       \r
+                       if( $animePath && $usePch ){\r
+                               $param .= '<param name="thumbnail_type" value="animation" />';\r
+                               $param .= "<param name=\"pch_file\" value=\"{$CONF['MediaURL']}{$animePath}\" />";\r
+                       } else {\r
+                               $param .= "<param name=\"image_canvas\" value=\"{$CONF['MediaURL']}{$file}\" />";\r
+                       }\r
+                       \r
+                       if( $ow ){\r
+                               list($prefix, ) = explode('-', basename($file), 2);\r
+                       } else {\r
+                               $prefix = $this->_getFilePrefix();\r
+                       }\r
+               } else {\r
+                       $prefix = $this->_getFilePrefix();\r
+                       $ow = 0;\r
+               }\r
+               \r
+               $vars = array (\r
+                               'w' => $w,\r
+                               'h' => $h,\r
+                               'user' => $member->getDisplayName(),\r
+                               'loginkey' => $this->_generateLoginkey(),\r
+                               'prefix' => $prefix,\r
+                               'charset' => _CHARSET,\r
+                               'header' => $header,\r
+                               'beforeapplet' => $beforeapplet,\r
+                               'param' => $param,\r
+                               'afterapplet' => $afterapplet,\r
+                               'copyright' => $copyright,\r
+                               'ow' => $ow,\r
+                               'file' => $file,\r
+                               'imgJpeg' => ( $this->getOption('defaultImgType') == 'AUTO' ) ? 'true' : 'false',\r
+                               'imgDecrease' => ( $this->getOption('defaultImgType') == 'AUTO' ) ? $this->getOption('defaultImgDecrease') : '0',\r
+                               'imgCompress' => ( $this->getOption('defaultImgType') == 'AUTO' ) ? $this->getOption('defaultImgCompress') : '0',\r
+                               'quality' => $quality,\r
+               );\r
+               \r
+               echo $applet->getPageTemplate($vars);\r
+               return '';\r
+       }\r
+       \r
+       // return list($animeFile, $appletName)\r
+       function findAppletByImg($file){\r
+               global $DIR_MEDIA;\r
+               $collection = intval(dirname($file));\r
+               $basename = basename($file, '.jpg');\r
+               $basename = basename($basename, '.png');\r
+                               \r
+               foreach( $this->applets as $key => $applet  ){\r
+                       foreach( $applet->animeExt as $ext ){\r
+                               $anime = $DIR_MEDIA . $collection . '/' .  $basename . $ext;\r
+                               if( file_exists( $anime ) ){\r
+                                       $appletName = $key;\r
+                                       $animeFile = $collection . '/' .  $basename . $ext;\r
+                                       $ret = Array($animeFile, $appletName);\r
+                                       return $ret;\r
+                               }\r
+                       }\r
+               }\r
+               return null;\r
+       }\r
+       \r
+       function getFileInfo($animeFile){\r
+               global $DIR_MEDIA;\r
+               \r
+               list(,$ext) = explode('.', basename($animeFile), 2);\r
+               $animeFile = $DIR_MEDIA . $animeFile;\r
+               \r
+               $fileInfo = Array();\r
+               if( is_readable($animeFile) && ($ext == 'spch' || $ext == 'rpch') ){\r
+                       $fp = fopen($animeFile, 'r');\r
+                       while (!feof ($fp)) {\r
+                               $line = fgets($fp, 100);\r
+                               if (preg_match('/([a-zA-Z0-9_.-]+)=([a-zA-Z0-9_.-]+)/i', $line, $matches)) {\r
+                                       list(, $key, $value, ) = $matches;\r
+                                       $fileInfo[$key] = $value;\r
+                               } else {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       fclose($fp);\r
+               }\r
+               return  $fileInfo;\r
+       }\r
+       \r
+       function _showViewer(){\r
+               global $member;\r
+               \r
+               if(     ! $file = requestVar('file') ){\r
+                       return _PAINT_fileIsNotSet;\r
+               }\r
+               if(     ! $type = requestVar('viewer') ){\r
+                       return _PAINT_viewerIsNotSet;\r
+               }\r
+\r
+               $w = intRequestVar('w') ? intRequestVar('w') : $this->getOption('defaultWidth');\r
+               $h = intRequestVar('h') ? intRequestVar('h') : $this->getOption('defaultHeight');\r
+\r
+               if(     ! $viewer = $this->viewers[$type] ){\r
+                       return _PAINT_canNotFindViewer .' viewer:' . $type;\r
+               }\r
+               if( $type == 'continue' ){\r
+                       if ( ! $member->isLoggedIn() )\r
+                               return _PAINT_NeedLogin;\r
+                       $collection = intval(dirname($file));\r
+                       if ( $collection != $member->getId() ){\r
+                               return _PAINT_illegalCollection;\r
+                       }\r
+               }\r
+               \r
+               $vars = array (\r
+                               'w' => intval($w),\r
+                               'h' => intval($h),\r
+                               'file' => $file,\r
+                               'charset' => _CHARSET,\r
+               );\r
+               \r
+               echo $viewer->getPageTemplate($vars);\r
+               return '';\r
+       }\r
+               \r
+       function _loadPlugin( $typelist = false, $reload = false ){\r
+               if( $this->isPluginLoaded && ( ! $reload ) )\r
+                       return ;\r
+               if( $this->isPluginLoaded ){\r
+                       $this->init();\r
+               }\r
+               \r
+               $this->isPluginLoaded = true;\r
+               \r
+               if( ! $typelist ){\r
+                       $typelist = 'Applet|Palette|Parser|Viewer';\r
+               }\r
+               \r
+               $pluginDir = $this->getDirectory();\r
+               $dirhandle = opendir( $pluginDir );\r
+               while ($filename = readdir($dirhandle)) {\r
+                       if (preg_match('/^('.$typelist.')_(.*)\.php$/i',$filename,$matches)) {\r
+                               list(, $type, $name, ) = $matches;\r
+                               \r
+                               $pluginPath = $pluginDir . $filename;\r
+                               if( ! is_readable( $pluginPath ) ){\r
+                                       $this->_warn(_PAINT_canNotReadFile . " file:$pluginPath, type:$type, name:$name");\r
+                                       continue;\r
+                               }\r
+                               \r
+                               require_once($pluginPath);\r
+                               if( class_exists($type . '_' . $name) ){\r
+                                       eval('$plugin =& new ' . $type . '_' . $name . '();');\r
+                                       $plugin->appletBaseUrl = $this->getAdminURL() . 'applet/';\r
+                                       $plugin->template =& $this->template;\r
+       \r
+                                       if( $plugin->enable ){\r
+                                               //$this->_info('Plugin installed: ' . $name);\r
+                                               switch( strtolower($type) ){\r
+                                                       case 'parser':\r
+                                                               $this->parsers[strtolower($name)] =& $plugin;\r
+                                                               break;\r
+                                                       case 'applet':\r
+                                                               $this->applets[strtolower($name)] =& $plugin;\r
+                                                               break;\r
+                                                       case 'palette':\r
+                                                               $this->palettes[strtolower($name)] =& $plugin;\r
+                                                               break;\r
+                                                       case 'viewer':\r
+                                                               $this->viewers[strtolower($name)] =& $plugin;\r
+                                                               break;\r
+                                                       default:\r
+                                                               // nothing\r
+                                                               $this->_warn('Unknown plugin: ' . $name);\r
+                                               }\r
+                                       } else {\r
+                                               $this->disabledPlugin[strtolower($type.'_'.$name)] =& $plugin;\r
+                                       }\r
+                               } else {\r
+                                       $this->_warn(_PAINT_canNotLoadClass . " file:$pluginPath, type:$type, name:$name");\r
+                                       continue;\r
+                               }\r
+                       }\r
+               }\r
+               closedir($dirhandle);\r
+       }\r
+       \r
+       function _postimg($parser){\r
+               global $member, $DIR_MEDIA;\r
+               \r
+               $parser =& $this->parsers[$parser];\r
+               if(! $parser ){\r
+                       $this->_warn('Parser not found');\r
+                       return 'Parser not found';\r
+               }\r
+               \r
+               $data =& $parser->parse();\r
+               // exist parse error\r
+               if( ! is_array($data) ){\r
+                       $this->_warn($data);\r
+                       return $data;\r
+               }\r
+               \r
+               // Login check\r
+               $user = '';\r
+               $loginkey = '';\r
+               if( $data['header'] ){\r
+                       if (preg_match('/user=([^&=]+)&loginkey=([^&=]+)&prefix=([^&=]+)&ow=([^&=]+)&applet=([^&=]+)/i', urldecode($data['header']), $word)) {\r
+                               list(, $user, $loginkey, $prefix, $ow, $applet, ) = $word;\r
+                       }\r
+               }\r
+               \r
+               if( ! MEMBER::exists($user) ){\r
+                       $this->_warn("User Not Found ( user:$user, loginkey:$loginkey, prefix:$prefix )");\r
+                       return _PAINT_UserNotFound;\r
+               }\r
+               \r
+               $member =& MEMBER::createFromName($user);\r
+               if ( ! $this->_checkLoginkey($loginkey, intval($member->getID())) ){\r
+                       $this->_warn("Invalid Ticket ( user:$user, loginkey:$loginkey, prefix:$prefix )");\r
+                       return _PAINT_InvalidTicket;\r
+               }\r
+               $member->loggedin = 1;\r
+               $this->_info("Login OK ( user:$user, loginkey:$loginkey, prefix:$prefix)");\r
+               $this->_info(count($data['images']) . ' images found.');\r
+               foreach( $data['size'] as $idx => $size ){\r
+                       $this->_info('DataSize['.$idx.']: '.$size);\r
+               }\r
+               \r
+               if( $prefix ){\r
+                       $this->_getFilePrefix($prefix);\r
+               } else {\r
+                       $this->_warn(_PAINT_canNotFindPrefix);\r
+                       $this->_getFilePrefix();                        \r
+               }\r
+               \r
+               $collection = intval($member->getID());\r
+               // ow delete\r
+               if( $ow ){\r
+                       foreach( Array('.jpg', '.png', '.pch', '.spch', '.rpch') as $ext ){\r
+                               if( file_exists( $file = $DIR_MEDIA . $collection . '/' . $this->_getFilePrefix() . '-' . NP_PAINT_IMAGE_NAME . $ext ) ){\r
+                                       if( unlink($file) ){\r
+                                               $this->_info(_PAINT_deleteFile . ' file:'. $file);\r
+                                       } else {\r
+                                               $this->_warn(_PAINT_deleteFile_failure . ' file:'. $file);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               foreach( $data['images'] as $idx => $imgdata ){\r
+                       $imgDir = $DIR_MEDIA . $collection;\r
+                       $tmpFileName = $this->_getFilePrefix() . '_'. $idx . '.tmp';\r
+                       \r
+                       $this->_info('tmpfile: '.$tmpFileName);\r
+                       $err = MEDIA::addMediaObjectRaw($collection, $tmpFileName, $imgdata);\r
+                       if($err){\r
+                               $this->_warn('addMediaObjectRaw Error: '. $err);\r
+                               return $err;\r
+                       }\r
+                       \r
+                       $imageSize = @GetImageSize($imgDir . '/' . $tmpFileName);\r
+                       // detect file type\r
+                       if($imageSize === false){\r
+                               switch( $applet ){\r
+                                       case 'paintbbs':\r
+                                               $suffix = '.pch';\r
+                                               break;\r
+                                       case 'shipainter':\r
+                                               $suffix = '.spch';\r
+                                               break;\r
+                                       case 'shipainterpro':\r
+                                               $suffix = '.rpch';\r
+                                               break;\r
+                               }\r
+                       } else {\r
+                               switch($imageSize[2]){\r
+                                       case IMAGETYPE_JPEG:\r
+                                               $suffix = '.jpg';                               \r
+                                               break;\r
+                                       case IMAGETYPE_PNG:\r
+                                               $suffix = '.png';\r
+                                               break;\r
+                                       default:\r
+                                               $suffix = '.dat';\r
+                               }\r
+                       }\r
+                       \r
+                       $filename = $this->_getFilePrefix() . '-' . NP_PAINT_IMAGE_NAME .$suffix;\r
+                       if( rename($imgDir . '/' . $tmpFileName, $imgDir . '/' . $filename ) === FALSE ){\r
+                               $this->_warn(_PAINT_rename_failure . ": {$tmpFileName} => {$filename}" );\r
+                       } else {\r
+                               $this->_info(_PAINT_rename_ok . ": {$tmpFileName} => {$filename}" );\r
+                       }\r
+                       \r
+                       \r
+                       if( !( function_exists('ImageTypes') && defined('IMG_JPG') && defined('IMG_PNG') )){\r
+                               $this->_info(_PAINT_GDNotSupported);\r
+                               continue;\r
+                       }\r
+                       \r
+                       if( $this->getOption('defaultImgType') == 'JPG' && $suffix == '.png' && (@ImageTypes() & IMG_JPG) ){\r
+                               $this->_info(_PAINT_convertToJpg);\r
+                               $imgres = @ImageCreateFromPNG($imgDir . '/' . $filename);\r
+                               if( $imgres ){\r
+                                       $suffix = '.jpg';\r
+                                       $filename = $this->_getFilePrefix() . '-'. NP_PAINT_IMAGE_NAME . $suffix;\r
+                                       $this->_info('convertedFilename: ' . $filename);        \r
+                                       if( @ImageJPEG($imgres, $imgDir . '/' . $filename, $this->getOption('defaultImgQuality'))){\r
+                                               $this->_info(_PAINT_convertToJpg_succeeded);\r
+                                               if( @unlink($imgDir . '/' . $filename) ){\r
+                                                       $this->_info(_PAINT_deleteFile . ':'. $filename);\r
+                                               } else {\r
+                                                       $this->_warn(_PAINT_deleteFile_failure .':'. $filename);\r
+                                               }\r
+                                       } else {\r
+                                               $this->_warn(_PAINT_convertToJpg_failure);\r
+                                       }\r
+                                       @ImageDestroy($imgres);\r
+                               } else {\r
+                                       $this->_warn(_PAINT_pngRead_failure);\r
+                               }\r
+                       }\r
+               }               \r
+               return '';\r
+       }\r
+               \r
+       function _getFilePrefix($prefix = ''){\r
+               if( $prefix )\r
+                       $this->filePrefix = $prefix;\r
+               if( ! $this->filePrefix )\r
+                       $this->filePrefix = date('YmdHis');\r
+//                     $this->filePrefix = uniqid('');\r
+               return $this->filePrefix;\r
+       }\r
+\r
+       function _showItemAddForm() {\r
+               global $member, $manager, $CONF;\r
+               $manager->loadClass('ADMIN');\r
+               \r
+               $query = 'SELECT tblog as blogid from '.sql_table('team').' where tmember=' . intval($member->getID()) . ' limit 1';\r
+               $res = sql_query($query);\r
+               if (mysql_num_rows($res) > 0) {\r
+                       $obj = mysql_fetch_object($res);\r
+                       $blogid = $obj->blogid;\r
+               } else {\r
+                       return _ERROR_NOTONTEAM;                        \r
+               }\r
+               \r
+               $body = '';\r
+               if( intRequestVar('w') && intRequestVar('h') && requestVar('prefix') ){\r
+                       $prefix = requestVar('prefix');\r
+                       \r
+                       $collection = intval($member->getID());\r
+                       $mediaobjects = MEDIA::getMediaListByCollection($collection, $prefix . '-'.NP_PAINT_IMAGE_NAME);\r
+                       \r
+                       $this->_info( Count($mediaobjects) . ' mediaobject(s) found.');\r
+                       \r
+                       if( Count($mediaobjects) > 0){\r
+                               foreach($mediaobjects as $mo){\r
+                                       if (preg_match('/\.(jpg|png)$/i', $mo->filename)){\r
+                                               $filename = $mo->filename;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               \r
+                               $vars = array (\r
+                                       'url' => $collection . '/' . $filename,\r
+                                       'w' => intRequestVar('w'),\r
+                                       'h' => intRequestVar('h'),\r
+                               );\r
+                               $body = TEMPLATE :: fill($this->getOption('bodyTpl'), $vars);\r
+                       }\r
+               }\r
+\r
+               $item['body'] = $body;\r
+               $item['title'] = '';\r
+               //default category\r
+               //$item['catid'] = '';\r
+\r
+               ob_start();\r
+               $factory =& new PAGEFACTORY($blogid);\r
+               $factory->createAddForm('bookmarklet',$item);\r
+               $content = ob_get_contents();\r
+               ob_end_clean();\r
+\r
+               $replace = '<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=' . _CHARSET . '" />\r
+<base href="' . $CONF['AdminURL'] . '" />';    \r
+               $content = preg_replace ("/<head>/", $replace, $content);\r
+               \r
+               $replace = '<form method="post" action="index.php" >';\r
+               $content = preg_replace ("/<form[^>]*>/", $replace, $content);\r
+               \r
+               echo $content;\r
+               return '';\r
+       }\r
+       \r
+       function _showOk(){\r
+               $vars = array(\r
+                       'charset' => _CHARSET,\r
+               );\r
+               $tpl = $this->template->fetch('ok', strtolower(__CLASS__));     \r
+               return $this->template->fill($tpl, $vars, false);\r
+       }\r
+               \r
+       function _info($msg) {\r
+               if ($this->getOption('debug') == 'yes') {\r
+                       ACTIONLOG :: add(INFO, 'Paint: '.$msg);\r
+               }\r
+       }\r
+\r
+       function _warn($msg) {\r
+               ACTIONLOG :: add(WARNING, 'Paint: '.$msg);\r
+       }\r
+\r
+       function _getAppletSelect($default = null){\r
+               if( $default ){\r
+                       $recomended = _PAINT_STAR;\r
+               } else {\r
+                       $recomended = '';\r
+                       $default = $this->getOption('defaultApplet');\r
+               }\r
+               \r
+               $ret = '<select name="applet">';\r
+               foreach( $this->applets as $key => $applet ){\r
+                       $selected = ( $default == $key ) ? 'selected="selected"' : '';\r
+                       $ret .= '<option value="' . $key . '" ' . $selected . ' >' . ($selected ? $recomended : '') .$applet->name .  '</option>' . "\n";\r
+               }\r
+               $ret .= '</select>';\r
+               return $ret;\r
+       }       \r
+       \r
+       function _getPaletteSelect(){\r
+               $ret = '<select name="palette">';\r
+               foreach( $this->palettes as $key => $palette ){\r
+                       $selected = ( $this->getOption('defaultPalette') == $key ) ? 'selected="selected"' : '';\r
+                       $ret .= '<option value="' . $key . '" ' . $selected . '>' . $palette->name .  '</option>' . "\n";\r
+               }\r
+               $ret .= '</select>';\r
+               return $ret;\r
+       }\r
+\r      function _getPaletteSelectExtra(){\r
+               foreach( $this->palettes as $key => $palette ){\r
+                       $ret .= $palette->getExtraOption();\r
+               }\r
+               return $ret;\r
+       }\r
+       \r
+       function _getQualitySelect($selected = null){\r
+               if(! $selected )\r
+                       $selected = $this->getOption('defaultAppletQuality');\r
+               $qualities = Range(1,5);\r
+               \r
+               $tpl = '<select name="quality">';\r
+               foreach( $qualities as $quality ){\r
+                       $tpl .= '<option value="' . $quality . '" '  .  ( $quality == $selected ? 'selected="selected" ' : '' )  . '>' . $quality . '</option>';\r
+               }\r
+               $tpl .= '</select>';\r
+               \r
+               return $tpl;\r
+       }\r
+       \r
+       function _generateLoginkey(){\r
+               global $member;\r
+               $memberid = $member->getID();\r
+               \r
+               $done = false;\r
+               $ticket = null;\r
+               while(!$done){\r
+                       $ticket = sha1(uniqid('').mt_rand(1,999999999));\r
+                       $query = sprintf('INSERT INTO ' . sql_table(NP_PAINT_TICKET_TABLE) \r
+                               . "(ticket, member) VALUES('%s', %s)"\r
+                               , mysql_real_escape_string( $ticket )\r
+                               , mysql_real_escape_string( intval($memberid) )\r
+                       );\r
+                       if( sql_query($query) ) $done = true;\r
+               }\r
+               return $ticket;\r
+       }\r
+       \r
+       function _checkLoginkey($ticket, $memberid ){\r
+               $query = sprintf('SELECT count(*) as result FROM ' . sql_table(NP_PAINT_TICKET_TABLE) \r
+                       . " WHERE ticket = '%s' AND member = %s AND generated > DATE_SUB(NOW(),INTERVAL %s SECOND)"\r
+                       , mysql_real_escape_string( $ticket )\r
+                       , mysql_real_escape_string( intval($memberid) )\r
+                       , mysql_real_escape_string( NP_PAINT_TICKET_LIFETIME )\r
+               );\r
+               $result = quickQuery($query) ? true : false ;\r
+\r
+               $query = sprintf('DELETE FROM ' . sql_table(NP_PAINT_TICKET_TABLE)\r
+                       . " WHERE ticket = '%s' OR generated < DATE_SUB(NOW(),INTERVAL %s SECOND)"\r
+                       , mysql_real_escape_string( $ticket )\r
+                       , mysql_real_escape_string( NP_PAINT_TICKET_LIFETIME )\r
+               );\r
+               sql_query($query);\r
+               \r
+               return $result;\r
+       }\r
+       \r
+       function _getLoginkey(){\r
+               $ret  = '<?xml version="1.0" encoding="utf-8" ?>'."\n";\r
+               $ret .= '<loginkey>'.$this->_generateLoginkey().'</loginkey>'."\n";\r
+               return $ret;\r
+       }\r
+}\r