]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/FileInfo.php
Activated Id substitution for Subversion
[SourceForge/phpwiki.git] / lib / plugin / FileInfo.php
1 <?php // -*-php-*-
2 rcs_id('$Id$');
3 /*
4  Copyright 2005,2007 $ThePhpWikiProgrammingTeam
5  
6  This file is part of PhpWiki.
7
8  PhpWiki is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  PhpWiki is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /**
24  * This plugin displays the version, date, size, perms of an uploaded file.
25  * Only files relative and below to the uploads path can be handled.
26  *
27  * Usage:
28  *   <?plugin FileInfo file=Upload:setup.exe display=version,date ?>
29  *   <?plugin FileInfo file=Upload:setup.exe display=name,version,date 
30  *                     format="%s (version: %s, date: %s)" ?>
31  *
32  * @author: ReiniUrban
33  */
34
35 class WikiPlugin_FileInfo
36 extends WikiPlugin
37 {
38     function getName () {
39         return _("FileInfo");
40     }
41
42     function getDescription () {
43         return _("Display file information like version,size,date,... of uploaded files.");
44     }
45
46     function getVersion() {
47         return preg_replace("/[Revision: $]/", '',
48                             "\$Revision: 1.9 $");
49     }
50
51     function getDefaultArguments() {
52         return array(
53                      'file'      => false, // relative path from PHPWIKI_DIR. (required)
54                      'display'   => false, // version,phonysize,size,date,mtime,owner,name,path,dirname,link.  (required)
55                      'format'    => false, // printf format string with %s only, all display modes 
56                      'quiet'     => false  // print no error if file not found
57                                            // from above vars return strings (optional)
58                     );
59     }
60
61     function run($dbi, $argstr, &$request, $basepage) {
62         $args = $this->getArgs($argstr, $request);
63         extract($args);
64         if (!$file)
65             return $this->error(sprintf(_("A required argument '%s' is missing."), 'file'));
66         if (!$display)
67             return $this->error(sprintf(_("A required argument '%s' is missing."), 'display'));
68         if (string_starts_with($file, "Upload:")) {
69             $file = preg_replace("/^Upload:(.*)$/", getUploadFilePath()."\\1", $file);
70             $is_Upload = 1;
71         }
72         $dir = getcwd();
73         if (defined('PHPWIKI_DIR')) {
74             chdir(PHPWIKI_DIR);
75         }
76         if (!file_exists($file)) {
77             if ($quiet)
78                 return '';
79             else
80                 trigger_error("file \"$file\" not found", E_USER_WARNING);
81         }
82         // sanify $file name
83         $realfile = realpath($file);
84         // Hmm, allow ADMIN to check a local file? Only if its locked
85         if (string_starts_with($realfile, realpath(getUploadDataPath()))) {
86             $isuploaded = 1;
87         } else {
88             $page = $dbi->getPage($basepage);
89             $user = $request->getUser();
90             if ($page->getOwner() != ADMIN_USER or !$page->get('locked')) {
91                 // For convenience we warn the admin
92                 if ($quiet and $user->isAdmin())
93                     return HTML::span(array('title' => _("Output suppressed. FileInfoPlugin with local files require a locked page.")),
94                                       HTML::em(_("page not locked")));
95                 else
96                     return $this->error("Invalid path \"$file\". Only ADMIN can allow local paths, and the page must be locked.");
97             }
98         }
99         $s = array();
100         $modes = explode(",", $display);
101         foreach ($modes as $mode) {
102             switch ($mode) {
103             case 'version':  $s[] = $this->exeversion($file); break;
104             case 'size':     $s[] = filesize($file); break;
105             case 'phonysize':$s[] = $this->phonysize(filesize($file)); break;
106             case 'date':     $s[] = strftime("%x %X", filemtime($file)); break;
107             case 'mtime':    $s[] = filemtime($file); break;
108             case 'owner':    $o = posix_getpwuid(fileowner($file)); $s[] = $o['name']; break;
109             case 'group':    $o = posix_getgrgid(filegroup($file)); $s[] = $o['name']; break;
110             case 'name':     $s[] = basename($file); break;
111             case 'path':     $s[] = $file; break;
112             case 'dirname':  $s[] = dirname($file); break;
113             case 'magic':    $s[] = $this->magic($file); break;
114             case 'mime-typ': $s[] = $this->mime_type($file); break;
115             case 'link':    
116                 if ($is_Upload) {
117                     $s[] = " [".$args['file'] . "]"; 
118                 } elseif ($isuploaded) {
119                     // will fail with user uploads
120                     $s[] = " [Upload:".basename($file)."]"; 
121                 } else {
122                     $s[] = " [".basename($file)."] "; 
123                 }
124                 break;
125             default:
126                 if (!$quiet)
127                     return $this->error(sprintf(_("Unsupported argument: %s=%s"), 'display', $mode)); 
128                 else return '';
129                 break;
130             }
131         }
132         chdir($dir);
133         if (!$format) {
134             $format = '';
135             foreach ($s as $x) { $format .= " %s"; }
136         }
137         array_unshift($s, $format);
138         // $x, array($i,$j) => sprintf($x, $i, $j)
139         $result = call_user_func_array("sprintf", $s);
140         if (in_array('link', $modes)) {
141             require_once("lib/InlineParser.php");
142             return TransformInline($result, 2, $basepage);
143         } else {
144             return $result;
145         }
146     }
147
148     function magic($file) {
149         if (function_exists('finfo_file') or loadPhpExtension('fileinfo')) {
150             // Valid finfo_open (i.e. libmagic) options:
151             // FILEINFO_NONE | FILEINFO_SYMLINK | FILEINFO_MIME | FILEINFO_COMPRESS | FILEINFO_DEVICES |
152             // FILEINFO_CONTINUE | FILEINFO_PRESERVE_ATIME | FILEINFO_RAW
153             $f = finfo_open(/*FILEINFO_MIME*/);
154             $result = finfo_file(realpath($file));
155             finfo_close($res);
156             return $result;
157         }
158         return '';
159     }
160
161     function mime_type($file) {
162         return '';
163     }
164
165     function _formatsize ($n, $factor, $suffix = '') {
166         if ($n > $factor) {
167             $b = $n / $factor;
168             $n -= floor($factor * $b);
169             return number_format($b, $n ? 3 : 0). $suffix;
170         }
171     }
172     function phonysize ($a) {
173         $factor = 1024 * 1024 * 1000;
174         if ($a > $factor)
175             return $this->_formatsize($a, $factor, ' GB');
176         $factor = 1024 * 1000;
177         if ($a > $factor)
178             return $this->_formatsize($a, $factor, ' MB');
179         $factor = 1024;
180         if ($a > $factor)
181             return $this->_formatsize($a, $factor, ' KB');
182         if ($a > 1)
183             return $this->_formatsize($a, 1, ' byte');
184         else
185             return $a;
186     }
187
188     function exeversion($file) {
189         if (!isWindows()) return "?";
190         if (class_exists('ffi') or loadPhpExtension('ffi'))
191             return $this->exeversion_ffi($file);
192         if (function_exists('res_list_type') or loadPhpExtension('win32std'))
193             return $this->exeversion_resopen($file);
194         return exeversion_showver($file);
195         return '';
196     }
197
198     // http://www.codeproject.com/dll/showver.asp
199     function exeversion_showver($file) {
200         $path = realpath($file);
201         $result = `showver $path`; 
202         return "?";
203     }
204
205     function exeversion_ffi($file) {
206         if (!DEBUG)
207             return "?"; // not yet stable
208         
209         if (function_exists('ffi') or loadPhpExtension('ffi')) {
210             $win32_idl = "
211 struct VS_FIXEDFILEINFO {
212         DWORD dwSignature;
213         DWORD dwStrucVersion;
214         DWORD dwFileVersionMS;
215         DWORD dwFileVersionLS;
216         DWORD dwProductVersionMS;
217         DWORD dwProductVersionLS;
218         DWORD dwFileFlagsMask;
219         DWORD dwFileFlags;
220         DWORD dwFileOS;
221         DWORD dwFileType;
222         DWORD dwFileSubtype;
223         DWORD dwFileDateMS;
224         DWORD dwFileDateLS;
225 };
226 struct VS_VERSIONINFO { struct VS_VERSIONINFO
227   WORD  wLength; 
228   WORD  wValueLength; 
229   WORD  wType; 
230   WCHAR szKey[1]; 
231   WORD  Padding1[1]; 
232   VS_FIXEDFILEINFO Value; 
233   WORD  Padding2[1]; 
234   WORD  Children[1]; 
235 };
236 [lib='kernel32.dll'] DWORD GetFileVersionInfoSizeA(char *szFileName, DWORD *dwVerHnd);
237 [lib='kernel32.dll'] int GetFileVersionInfoA(char *sfnFile, DWORD dummy, DWORD size, struct VS_VERSIONINFO *pVer);
238 ";
239             $ffi = new ffi($win32_idl);
240             $dummy = 0; // &DWORD
241             $size = $ffi->GetFileVersionInfoSizeA($file, $dummy);
242             //$pVer = str_repeat($size+1);
243             $pVer = new ffi_struct($ffi, "VS_VERSIONINFO");
244             if ($ffi->GetFileVersionInfoA($file, 0, $size, $pVer) 
245                 and $pVer->wValueLength) {
246                 // analyze the VS_FIXEDFILEINFO(Value);
247                 // $pValue = new ffi_struct($ffi, "VS_FIXEDFILEINFO");
248                 $pValue =& $pVer->Value;
249                 return sprintf("%d.%d.%d.%d",
250                                $pValue->dwFileVersionMS >> 16,
251                                $pValue->dwFileVersionMS & 0xFFFF,
252                                $pValue->dwFileVersionLS >> 16, 
253                                $pValue->dwFileVersionLS & 0xFFFF);
254             }
255         }
256     }
257
258     // Read "RT_VERSION/VERSIONINFO" exe/dll resource info for MSWin32 binaries
259     // The "win32std" extension is not ready yet to pass back a VERSIONINFO struct
260     function exeversion_resopen($file) {
261         if (function_exists('res_list_type') or loadPhpExtension('win32std')) {
262             // See http://msdn.microsoft.com/workshop/networking/predefined/res.asp
263             $v = file_get_contents('res://'.realpath($file).urlencode('/RT_VERSION/#1'));
264             if ($v) {
265                 // This is really a binary VERSIONINFO block, with lots of
266                 // nul bytes (widechar) which cannot be transported as string.
267                 return "$v";
268             }
269             else {
270                 $h = res_open(realpath($file));
271                 $v = res_get($h, 'RT_VERSION', 'FileVersion');
272                 res_close($h);
273                 if ($v) return $v;
274
275                 $h = res_open(realpath($file));
276                 $v = res_get($h, '#1', 'RT_VERSION', 1);
277                 res_close($h);
278                 if ($v) return $v;
279             }
280               
281             /* The version consists of two 32-bit integers, defined by four 16-bit integers. 
282                For example, "FILEVERSION 3,10,0,61" is translated into two doublewords: 
283                0x0003000a and 0x0000003d, in that order. */
284 /*          
285         $h = res_open(realpath($file));
286             
287         echo "Res list of '$file': \n";
288         $list= res_list_type($h, true);
289         if( $list===FALSE ) err( "Can't list type" );
290         
291         for( $i= 0; $i<count($list); $i++ ) {
292                 echo $list[$i]."\n";
293                 $res= res_list($h, $list[$i]);
294                 for( $j= 0; $j<count($res); $j++ ) {
295                         echo "\t".$res[$j]."\n";
296                 }
297         }
298         echo "Res get: ".res_get( $h, 'A_TYPE', 'A_RC_NAME' )."\n\n";
299         res_close( $h );            
300 */
301             if ($v)
302                 return "$v";
303             else 
304                 return "";
305         } else {
306             return "";
307         }
308         
309     }
310 };
311
312 /* 
313  $Log: not supported by cvs2svn $
314  Revision 1.8  2008/05/17 06:26:57  vargenau
315  Check PHPWIKI_DIR is defined
316
317  Revision 1.7  2007/08/25 18:06:05  rurban
318  fix Upload: links
319
320  Revision 1.6  2007/01/04 16:42:31  rurban
321  Add quiet argument. Allow local files if owner == ADMIN and page == locked.
322
323  Revision 1.5  2006/08/25 22:10:16  rurban
324  fix docs: FileVersion => FileInfo
325
326  Revision 1.4  2005/10/29 14:18:47  rurban
327  add display=phonysize
328
329  Revision 1.3  2005/10/29 13:35:00  rurban
330  fix Log:, add chdir() if not in PHPWIKI_DIR, fix ->warning
331
332
333 */
334
335 // For emacs users
336 // Local Variables:
337 // mode: php
338 // tab-width: 8
339 // c-basic-offset: 4
340 // c-hanging-comment-ender-p: nil
341 // indent-tabs-mode: nil
342 // End:
343 ?>