OSDN Git Service

MitasNom 0.6.0
[nucleus-jp/nucleus-plugins.git] / trunk / NP_TrimImage / NP_TrimImage.php
1 <?php
2 // vim: tabstop=2:shiftwidth=2
3
4 /**
5   * NP_TrimImage ($Revision: 1.11 $)
6   * by nakahara21 ( http://nakahara21.com/ )
7   * by hsur ( http://blog.cles.jp/np_cles/ )
8   * $Id: NP_TrimImage.php,v 1.11 2008-05-02 17:23:20 hsur Exp $
9   *
10   * Based on NP_TrimImage 1.0 by nakahara21
11   * http://nakahara21.com/?itemid=512
12 */
13
14 /*
15   * Copyright (C) 2004-2006 nakahara21 All rights reserved.
16   * Copyright (C) 2006-2008 cles All rights reserved.
17   *
18   * This program is free software; you can redistribute it and/or
19   * modify it under the terms of the GNU General Public License
20   * as published by the Free Software Foundation; either version 2
21   * of the License, or (at your option) any later version.
22   * 
23   * This program is distributed in the hope that it will be useful,
24   * but WITHOUT ANY WARRANTY; without even the implied warranty of
25   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26   * GNU General Public License for more details.
27   * 
28   * You should have received a copy of the GNU General Public License
29   * along with this program; if not, write to the Free Software
30   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
31   * 
32   * In addition, as a special exception, mamio and cles gives
33   * permission to link the code of this program with those files in the PEAR
34   * library that are licensed under the PHP License (or with modified versions
35   * of those files that use the same license as those files), and distribute
36   * linked combinations including the two. You must obey the GNU General Public
37   * License in all respects for all of the code used other than those files in
38   * the PEAR library that are licensed under the PHP License. If you modify
39   * this file, you may extend this exception to your version of the file,
40   * but you are not obligated to do so. If you do not wish to do so, delete
41   * this exception statement from your version.
42 */
43
44 //history
45 //      0.2:    $archive, $blogid and $catid suppot ($exmode=all ready)
46 //                      echos 'no images' 
47 //      0.3:    add strtolower 
48 //                      Initialize $this->exquery
49 //      0.5:    use createGlobalItemLink
50 //                      sql_table support :-P
51 //      0.6:    parameter supports blogid and catid
52 //      0.7:    supports templatevar
53 //                      supports popup() 
54 //      0.8:    supports gif
55 //      0.9:    doTemplateVar calls DB data for other PreItem Plugin
56 //      0.9:    change '&' to '&amp;'
57 //      1.1:    NP_Paint support.
58 //              Security Fix.
59 //      2.0:    use phpThumb() (http://phpthumb.sourceforge.net)
60 //      2.1:    update regex
61 //              add alt/title attribute
62 //              bug fix
63 //  2.2:        support <img /> tag. 
64 //                              doTemplateVar() bug fix.
65 //                              Add ENT_QUOTES to htmlspecialchars()
66 //                              Add ExtractImageMode
67 //  2.2.1:      update phpThumb() 1.7.7 . 
68 //              bug fix 
69 //  2.2.2:      update enableLeftTop.patch
70 //  2.3.0:  add itemcat mode
71
72 define('NP_TRIMIMAGE_FORCE_PASSTHRU', true); //passthru(standard)
73 //define('NP_TRIMIMAGE_FORCE_PASSTHRU', false); //redirect(advanced)
74
75 define('NP_TRIMIMAGE_CACHE_MAXAGE', 86400 * 30); // 30days
76 define('NP_TRIMIMAGE_PREFER_IMAGEMAGICK', false);
77
78 require_once(dirname(__FILE__).'/sharedlibs/sharedlibs.php');
79 require_once('phpthumb/phpthumb.functions.php');
80 require_once('phpthumb/phpthumb.class.php');
81
82 class NP_TrimImage extends NucleusPlugin {
83         function getName() {
84                 return 'TrimImage';
85         }
86
87         function getAuthor() {
88                 return 'nakahara21 + hsur';
89         }
90
91         function getURL() {
92                 return 'http://blog.cles.jp/np_cles/category/31/subcatid/15';
93         }
94
95         function getVersion() {
96                 return '2.3.0';
97         }
98
99         function supportsFeature($what) {
100                 switch ($what) {
101                         case 'SqlTablePrefix' :
102                                 return 1;
103                         default :
104                                 return 0;
105                 }
106         }
107
108         function getDescription() {
109                 return 'Trim image in items, and embed these images.';
110         }
111                 
112         function getEventList() {
113                 return array ('PostAddItem', 'PostUpdateItem', 'PostDeleteItem',);
114         }
115         
116         function event_PostAddItem(& $data) {
117                 $this->_clearCache();
118         }
119         function event_PostUpdateItem(& $data) {
120                 $this->_clearCache();
121         }
122         function event_PostDeleteItem(& $data) {
123                 $this->_clearCache();
124         }
125         function _clearCache() {
126                 /*
127                 $phpThumb = new phpThumb();
128                 foreach ($this->phpThumbParams as $paramKey => $paramValue) {
129                         $phpThumb->setParameter($paramKey, $paramValue);
130                 }
131                 $phpThumb->setParameter('config_cache_maxage', 1);
132                 $phpThumb->CleanUpCacheDirectory();
133                 var_dump($phpThumb);
134                 */
135         }
136
137         function init() {
138                 global $DIR_MEDIA;
139                 $this->fileex = array ('.gif', '.jpg', '.png');
140                 $cacheDir = $DIR_MEDIA.'phpthumb/';
141                 $cacheDir = (is_dir($cacheDir) && @ is_writable($cacheDir)) ? $cacheDir : null;
142                 
143                 $this->phpThumbParams = array(
144                         'config_document_root' => $DIR_MEDIA,
145                         'config_cache_directory' => $cacheDir,
146                         'config_cache_disable_warning' => true,
147                         'config_cache_directory_depth' => 0,
148                         'config_cache_maxage' => NP_TRIMIMAGE_CACHE_MAXAGE,
149                         'config_cache_maxsize' => 10 * 1024 * 1024, // 10MB
150                         'config_cache_maxfiles' => 1000,
151                         'config_cache_source_filemtime_ignore_local' => true,
152                         'config_cache_cache_default_only_suffix' => '',
153                         'config_cache_prefix' => 'phpThumb_cache',
154                         'config_cache_force_passthru' => NP_TRIMIMAGE_FORCE_PASSTHRU,
155                         'config_max_source_pixels' => 3871488, //4Mpx
156                         'config_output_format' => 'jpg',
157                         'config_disable_debug' => true,
158                         'config_prefer_imagemagick' => NP_TRIMIMAGE_PREFER_IMAGEMAGICK,
159                 );
160         }
161
162         function getCategoryIDFromItemID($itemid) {
163                 return quickQuery('SELECT icat as result FROM ' . sql_table('item') . ' WHERE inumber=' . intval($itemid) );
164         }
165         
166         function doSkinVar($skinType, $amount = 10, $wsize = 80, $hsize = 80, $point = 0, $random = 0, $exmode = '', $titlemode = '', $includeImg = 'true') {
167                 global $CONF, $manager, $blog;
168                 if ($blog) {
169                         $b = & $blog;
170                 } else {
171                         $b = & $manager->getBlog($CONF['DefaultBlog']);
172                 }
173                 
174                 if (!is_numeric($amount))
175                         $amount = 10;
176                 if (!is_numeric($hsize))
177                         $hsize = 80;
178                 if (!is_numeric($wsize))
179                         $wsize = 80;
180                 $point = ($point == 'lefttop') ? true : false;
181                 $includeImg = ( $includeImg == 'true' ) ? true : false;
182                 
183                 $this->exquery = '';
184
185                 switch ($skinType) {
186                         case 'archive' :
187                                 global $archive;
188                                 $year = $month = $day = '';
189                                 sscanf($archive, '%d-%d-%d', $year, $month, $day);
190                                 if (empty ($day)) {
191                                         $timestamp_start = mktime(0, 0, 0, $month, 1, $year);
192                                         $timestamp_end = mktime(0, 0, 0, $month +1, 1, $year); // also works when $month==12
193                                 } else {
194                                         $timestamp_start = mktime(0, 0, 0, $month, $day, $year);
195                                         $timestamp_end = mktime(0, 0, 0, $month, $day +1, $year);
196                                 }
197                                 $this->exquery .= ' and itime >= ' . mysqldate($timestamp_start)
198                                                                         .' and itime < ' . mysqldate($timestamp_end);
199
200                                 //break;
201                         default :
202                                 if ($exmode == '' || $exmode == 'itemcat') {
203                                         global $catid, $itemid;
204                                         if ($catid)
205                                                 $this->exquery .= ' and icat = '.intval($catid);
206                                         elseif( $exmode == 'itemcat' && $itemid )
207                                                 $this->exquery .= ' and icat = '.intval( $this->getCategoryIDFromItemID($itemid) );
208                                         else
209                                                 $this->exquery .= ' and iblog = '.intval($b->getID());
210                                 } elseif ($exmode == 'all') {
211                                         // nothing
212                                 } else {
213                                         $spbid = $spcid = array ();
214                                         $spid_array = explode('/', $exmode);
215                                         foreach ($spid_array as $spid) {
216                                                 $type = substr($spid, 0, 1);
217                                                 $type_id = intval(substr($spid, 1));
218                                                 if( (!$type) || (!$type_id) ) continue;
219                                                 
220                                                 switch($type){
221                                                         case 'b':
222                                                                 $spbid[] = $type_id;
223                                                                 break;
224                                                         case 'c':
225                                                                 $spcid[] = $type_id;
226                                                                 break;
227                                                 }
228                                         }
229                                         if ($spbid){
230                                                 $this->exquery .= ' and iblog IN ('.implode(',', $spbid).') ';
231                                         }
232                                         if ($spcid) {
233                                                 $this->exquery .= ' and icat IN ('.implode(',', $spcid).') ';
234                                         }
235                                 }
236                 }
237
238                 $filelist = array ();
239                 $this->imglists = array ();
240                 $this->imgfilename = array ();
241                 $random = $random ? true : false;
242                 if (!($filelist = $this->listup($amount, $random, $includeImg))) {
243                         //echo 'No images here.';
244                         return;
245                 }
246
247                 $amount = min($amount, count($filelist));
248                 echo '<div>';
249                 for ($i = 0; $i < $amount; $i ++) {
250                         $itemlink = $this->createGlobalItemLink($filelist[$i][1], ''); // why not createItemLink ?
251                         //                      $itemlink = $this->createItemLink($filelist[$i][1]);
252                         echo '<a href="'.$itemlink.'">';
253
254                         $src = '';
255                         if (!$this->phpThumbParams['config_cache_force_passthru']) {
256                                 $src = $this->createImage($filelist[$i][0], $wsize, $hsize, $point, true);
257                         }
258                         if (!$src) {
259                                 $src = htmlspecialchars($CONF['ActionURL'], ENT_QUOTES)
260                                                 .'?action=plugin&amp;name=TrimImage&amp;type=draw'.'&amp;p='
261                                                 .$filelist[$i][0].'&amp;wsize='.$wsize.'&amp;hsize='.$hsize
262                                                 . ($point ? '&amp;pnt=lefttop' : '');
263                         }
264                         
265                         if($titlemode == 'item')
266                                 $title = ($filelist[$i][4]) ? $filelist[$i][4] : $filelist[$i][2];
267                         else
268                                 $title = ($filelist[$i][2]) ? $filelist[$i][2] : $filelist[$i][4];
269
270                         echo '<img src="'.$src.'" '                     
271                                 . ( $wsize ? 'width="'.$wsize.'"'  : '' )
272                                 . ( $hsize ? 'height="'.$hsize.'"' : '' )
273                                 . 'alt="'.htmlspecialchars($title, ENT_QUOTES)
274                                 . '" title="'.htmlspecialchars($title, ENT_QUOTES).'"/>';
275                         echo "</a>\n";
276                 }
277                 echo "</div>\n";
278         }
279
280         function listup($amount = 10, $random = false, $includeImg = true) {
281                 global $CONF, $manager, $blog;
282                 if ($blog) {
283                         $b = & $blog;
284                 } else {
285                         $b = & $manager->getBlog($CONF['DefaultBlog']);
286                 }
287
288                 $query = 'SELECT inumber as itemid, ititle as title, ibody as body, iauthor, itime, imore as more,';
289                 $query .= ' icat as catid, iclosed as closed';
290                 $query .= ' FROM '.sql_table('item');
291                 $query .= ' WHERE idraft = 0';
292                 $query .= ' and itime <= '.mysqldate($b->getCorrectTime()); // don't show future items!
293                 $query .= $this->exquery;
294                 $query .= ' ORDER BY itime DESC LIMIT '.intval($amount * 10);
295
296                 $res = sql_query($query);
297
298                 if (!mysql_num_rows($res))
299                         return FALSE;
300
301                 while ($it = mysql_fetch_object($res)) {
302                         $txt = $it->body.$it->more;
303                         if (preg_match_all("/<%(image|popup|paint)\((.*?)\)%>/s", $txt, $imgpnt))
304                                 @ array_walk($imgpnt[2], array (& $this, "exarray"), array ($it->itemid, $it->iauthor, $it->title));
305
306                         if ($includeImg && preg_match_all("/<img (.*?)>/s", $txt, $imgtmp)){
307                                 foreach($imgtmp[1] as $tmp){
308                                         $this->exarray($tmp, null, array($it->itemid, $it->iauthor, $it->title), true);
309                                 }
310                         }
311
312                         if (count($this->imglists) >= $amount)
313                                 break;
314                 }
315                 mysql_free_result($res);
316
317                 if ($random)
318                         shuffle($this->imglists);
319                 $this->imglists = array_slice($this->imglists, 0, $amount);
320                 return $this->imglists;
321         }
322
323         function exarray($imginfo, $key, $params, $isImg = false) {
324                 global $CONF;
325                 if ($isImg){
326                         if( preg_match_all('/(src|width|height|alt|title)=\"(.*?)\"/i', $imginfo, $matches) ) {
327                                 $index = 0;
328                                 $param = array();
329                                 foreach( $matches[1] as $type ){
330                                         $param[$type] = $matches[2][$index];                                            
331                                         $index++;
332                                 }
333                                 if( $param['src'] && ( strpos($param['src'], $CONF['MediaURL']) === 0 ) ){
334                                         $imginfo = substr( $param['src'], strlen($CONF['MediaURL']) )
335                                         . '|' . $param['width']
336                                         . '|' . $param['height']
337                                         . '|' . ( $param['title'] ? $param['tiltle'] : $param['alt']);
338                                 }
339                         } else {
340                                 return;
341                         }
342                 }
343                 
344                 list ($url, $w, $h, $alt, $ext) = explode("|", $imginfo, 5);
345                 if (!in_array(strtolower(strrchr($url, ".")), $this->fileex))
346                         return;
347                 if (in_array($url, $this->imgfilename))
348                         return;
349                 $this->imgfilename[] = $url;
350                 if (!strstr($url, '/')) {
351                         $url = $params[1].'/'.$url;
352                 }
353                 $this->imglists[] = array ($url, $params[0], $alt, $ext, $params[2]);
354         }
355
356         function doTemplateVar(& $item, $wsize = 80, $hsize = 80, $point = 0, $maxAmount = 0, $titlemode = '', $includeImg = 'true') {
357                 global $CONF;
358                 if (!is_numeric($hsize))
359                         $hsize = 80;
360                 if (!is_numeric($wsize))
361                         $wsize = 80;
362                 $point = ($point == 'lefttop') ? true : false;
363                 $includeImg = ( $includeImg == 'true' ) ? true : false;
364                 
365                 $filelist = array ();
366                 $this->imglists = array ();
367                 $this->imgfilename = array ();
368                 //$txt = $item->body.$item->more;
369                 $txt = '';
370                 $q = 'SELECT ibody as body, imore as more, ititle as title FROM '.sql_table('item').' WHERE inumber='.intval($item->itemid);
371                 $r = sql_query($q);
372                 while ($d = mysql_fetch_object($r)) {
373                         $txt .= $d->body.$d->more;
374                 }
375
376                 if (preg_match_all("/<%(image|popup|paint)\((.*?)\)%>/s", $txt, $imgpnt))
377                         @ array_walk($imgpnt[2], array (& $this, "exarray"), array ($item->itemid, $item->authorid, $item->title));
378                         
379                 if ($includeImg && preg_match_all("/<img (.*?)>/s", $txt, $imgtmp)){
380                         foreach($imgtmp[1] as $tmp){
381                                 $this->exarray($tmp, null, array ($item->itemid, $item->authorid, $item->title), true);
382                         }
383                 }
384
385                 $filelist = $this->imglists;
386                 if (!$maxAmount)
387                         $amount = count($filelist);
388                 else
389                         $amount = min($maxAmount, count($filelist));
390
391                 if (!$amount) {
392                         $img_tag = '<img src="'.htmlspecialchars($CONF['ActionURL'], ENT_QUOTES).'?action=plugin&amp;name=TrimImage';
393                         $img_tag .= '&amp;type=draw&amp;p=non&amp;wsize='.$wsize.'&amp;hsize='.$hsize.$exq;
394                         $img_tag .= '" width="'.$wsize.'" height="'.$hsize.'" />';
395                         echo $img_tag;
396                 } else {
397                         for ($i = 0; $i < $amount; $i ++) {
398                                 $src = '';
399                                 if (!$this->phpThumbParams['config_cache_force_passthru']) {
400                                         $src = $this->createImage($filelist[$i][0], $wsize, $hsize, $point, true);
401                                 }
402                                 if (!$src) {
403                                         $src = htmlspecialchars($CONF['ActionURL'], ENT_QUOTES).'?action=plugin&amp;name=TrimImage&amp;type=draw'.'&amp;p='.$filelist[$i][0].'&amp;wsize='.$wsize.'&amp;hsize='.$hsize. ($point ? '&amp;pnt=lefttop' : '');
404                                 }
405                                 
406                                 if($titlemode == 'item')
407                                         $title = ($filelist[$i][4]) ? $filelist[$i][4] : $filelist[$i][2];
408                                 else
409                                         $title = ($filelist[$i][2]) ? $filelist[$i][2] : $filelist[$i][4];
410                                 
411                                 echo '<img src="'.$src.'" '                     
412                                         . ( $wsize ? 'width="'.$wsize.'"'  : '' )
413                                         . ( $hsize ? 'height="'.$hsize.'"' : '' )
414                                         . 'alt="'.htmlspecialchars($title, ENT_QUOTES)
415                                         . '" title="'.htmlspecialchars($title, ENT_QUOTES).'"/>';
416                                 }
417                 }
418         }
419
420         function doAction($type) {
421                 $w = is_numeric(requestVar('wsize')) ? requestVar('wsize') : 80;
422                 $h = is_numeric(requestVar('hsize')) ? requestVar('hsize') : 80;
423                 $isLefttop = (requestVar('pnt') == 'lefttop') ? true : false;
424
425                 switch ($type) {
426                         case 'draw' :
427                                 $this->createImage(requestVar('p'), $w, $h, $isLefttop);
428                                 break;
429                         default :
430                                 return 'No such action';
431                                 break;
432                 }
433         }
434
435         function createImage($p, $w, $h, $isLefttop, $cacheCheckOnly = false) {
436                 $phpThumb = new phpThumb();
437                 foreach ($this->phpThumbParams as $paramKey => $paramValue) {
438                         $phpThumb->setParameter($paramKey, $paramValue);
439                 }
440
441                 if($h) $phpThumb->setParameter('h', intval($h));
442                 if($w) $phpThumb->setParameter('w', intval($w));
443
444                 if ($p == 'non') {
445                         $bghexcolor = 'FFFFFF';
446                         if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) {
447                                 $phpThumb->setParameter('is_alpha', true);
448                                 ImageAlphaBlending($phpThumb->gdimg_source, false);
449                                 ImageSaveAlpha($phpThumb->gdimg_source, true);
450                                 $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, 127);
451                                 ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color);
452                         }
453                 } else {
454                         $phpThumb->setParameter('src', '/'.$p);
455                         if( $w && $h  )
456                                 $phpThumb->setParameter('zc', $isLefttop ? 2 : 1);
457                         else
458                                 $phpThumb->setParameter('aoe', 1);
459                 }
460
461                 // getCache     
462                 $phpThumb->cache_filename = null;
463                 $phpThumb->CalculateThumbnailDimensions();
464                 $phpThumb->SetCacheFilename();
465                 if (file_exists($phpThumb->cache_filename)) {
466                         $nModified = filemtime($phpThumb->cache_filename);
467                         if (time() - $nModified < NP_TRIMIMAGE_CACHE_MAXAGE) {
468                                 global $CONF;
469                                 preg_match('/^'.preg_quote($this->phpThumbParams['config_document_root'], '/').'(.*)$/', $phpThumb->cache_filename, $matches);
470                                 $fileUrl = $CONF['MediaURL'].$matches[1];
471                                 if ($cacheCheckOnly)
472                                         return $fileUrl;
473
474                                 header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT');
475                                 if (@ serverVar('HTTP_IF_MODIFIED_SINCE') 
476                                         && ($nModified == strtotime(serverVar('HTTP_IF_MODIFIED_SINCE'))) 
477                                         && @ serverVar('SERVER_PROTOCOL')
478                                 ) {
479                                         header(serverVar('SERVER_PROTOCOL').' 304 Not Modified');
480                                         return true;
481                                 }
482                                 if ($getimagesize = @ GetImageSize($phpThumb->cache_filename)) {
483                                         header('Content-Type: '.phpthumb_functions :: ImageTypeToMIMEtype($getimagesize[2]));
484                                 }
485                                 elseif (eregi('\.ico$', $phpThumb->cache_filename)) {
486                                         header('Content-Type: image/x-icon');
487                                 }
488                                 if ($this->phpThumbParams['config_cache_force_passthru']) {
489                                         @ readfile($phpThumb->cache_filename);
490                                 } else {
491                                         header('Location: '.$fileUrl);
492                                 }
493                                 return true;
494                         }
495                 }
496                 if ($cacheCheckOnly) {
497                         unset ($phpThumb);
498                         return false;
499                 }
500
501                 // generate
502                 $phpThumb->GenerateThumbnail();
503
504                 // putCache
505                 if (!rand(0, 20))
506                         $phpThumb->CleanUpCacheDirectory();
507                 $phpThumb->RenderToFile($phpThumb->cache_filename);
508                 @ chmod($phpThumb->cache_filename, 0666);
509
510                 // to browser
511                 $phpThumb->OutputThumbnail();
512                 unset ($phpThumb);
513                 return true;
514         }
515
516         function canEdit() {
517                 global $member, $manager;
518                 if (!$member->isLoggedIn())
519                         return 0;
520                 return $member->isAdmin();
521         }
522
523         function createGlobalItemLink($itemid, $extra = '') {
524                 global $CONF, $manager;
525                 $itemid = intval($itemid);
526                 if ($CONF['URLMode'] == 'pathinfo') {
527                         $link = $CONF['ItemURL'].'/item/'.$itemid;
528                 } else {
529                         $blogid = getBlogIDFromItemID($itemid);
530                         $b_tmp = & $manager->getBlog($blogid);
531                         $blogurl = $b_tmp->getURL();
532                         if (!$blogurl) {
533                                 $blogurl = $CONF['IndexURL'];
534                         }
535                         if (substr($blogurl, -4) != '.php') {
536                                 if (substr($blogurl, -1) != '/')
537                                         $blogurl .= '/';
538                                 $blogurl .= 'index.php';
539                         }
540                         $link = $blogurl.'?itemid='.$itemid;
541                 }
542                 return addLinkParams($link, $extra);
543         }
544 }