]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/FileInfo.php
This plugin displays the version, date, size, perms of an uploaded file.
[SourceForge/phpwiki.git] / lib / plugin / FileInfo.php
1 <?php // -*-php-*-
2 rcs_id('$Id: FileInfo.php,v 1.1 2005-10-29 09:00:05 rurban Exp $');
3 /*
4  Copyright 2005 $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 FileVersion file=uploads/setup.exe display=version,date ?>
29  *   <?plugin FileVersion file=uploads/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.1 $");
49     }
50
51     function getDefaultArguments() {
52         return array(
53                      'file'      => false, // relative path from PHPWIKI_DIR. (required)
54                      'display'   => false, // version,size,date,mtime,owner,name,path,dirname,link.  (required)
55                      'format'    => false, // printf format string with %s only, all display modes 
56                                            // from above vars return strings (optional)
57                     );
58     }
59
60     function run($dbi, $argstr, &$request, $basepage) {
61         extract($this->getArgs($argstr, $request));
62         if (!$file)
63             return $this->error(sprintf(_("A required argument '%s' is missing."), 'file'));
64         if (!$display)
65             return $this->error(sprintf(_("A required argument '%s' is missing."), 'display'));
66
67         // sanify $file name
68         if (!file_exists($file)) {
69             return $this->warning("file \"$file\" not found");
70         }
71         $realfile = realpath($file);
72         if (!string_starts_with($realfile, realpath(getUploadDataPath())))
73             return $this->warning("invalid path \"$file\"");
74         else 
75             $isuploaded = 1;
76         $s = array();
77         $modes = explode(",", $display);
78         foreach ($modes as $mode) {
79             switch ($mode) {
80             case 'version':  $s[] = $this->exeversion($file); break;
81             case 'size':     $s[] = filesize($file); break;
82             case 'date':     $s[] = strftime("%x %X", filemtime($file)); break;
83             case 'mtime':    $s[] = filemtime($file); break;
84             case 'name':     $s[] = basename($file); break;
85             case 'path':     $s[] = $file; break;
86             case 'dirname':  $s[] = dirname($file); break;
87             case 'magic':    $s[] = $this->magic($file); break;
88             case 'mime-typ': $s[] = $this->mime_type($file); break;
89             case 'link':    
90                 if ($isuploaded) {
91                     $s[] = "[Upload:".basename($file)."]"; 
92                 } else {
93                     $s[] = "[".basename($file)."]"; 
94                 }
95                 break;
96             default:
97                 return $this->error(sprintf(_("Unsupported argument: %s=%s"), 'display', $mode)); 
98                 break;
99             }
100         }
101         if (!$format) {
102             $format = '';
103             foreach ($s as $x) { $format .= " %s"; }
104         }
105         array_unshift($s, $format);
106         // $x, array($i,$j) => sprintf($x, $i, $j)
107         $result = call_user_func_array("sprintf", $s);
108         if (in_array('link', $modes)) {
109             require_once("lib/InlineParser.php");
110             return TransformInline($result);
111         } else {
112             return $result;
113         }
114     }
115
116     function magic($file) {
117         if (function_exists('finfo_file') or loadPhpExtension('fileinfo')) {
118             // Valid finfo_open (i.e. libmagic) options:
119             // FILEINFO_NONE | FILEINFO_SYMLINK | FILEINFO_MIME | FILEINFO_COMPRESS | FILEINFO_DEVICES |
120             // FILEINFO_CONTINUE | FILEINFO_PRESERVE_ATIME | FILEINFO_RAW
121             $f = finfo_open(/*FILEINFO_MIME*/);
122             $result = finfo_file(realpath($file));
123             finfo_close($res);
124             return $result;
125         }
126         return '';
127     }
128
129     function mime_type($file) {
130         return '';
131     }
132
133     function exeversion($file) {
134         if (!isWindows()) return "?";
135         if (class_exists('ffi') or loadPhpExtension('ffi'))
136             return $this->exeversion_ffi($file);
137         if (function_exists('res_list_type') or loadPhpExtension('win32std'))
138             return $this->exeversion_resopen($file);
139         return exeversion_showver($file);
140         return '';
141     }
142
143     // http://www.codeproject.com/dll/showver.asp
144     function exeversion_showver($file) {
145         $path = realpath($file);
146         $result = `showver $path`; 
147         return "?";
148     }
149
150     function exeversion_ffi($file) {
151         if (!DEBUG)
152             return "?"; // not yet stable
153         
154         if (function_exists('ffi') or loadPhpExtension('ffi')) {
155             $win32_idl = "
156 struct VS_FIXEDFILEINFO {
157         DWORD dwSignature;
158         DWORD dwStrucVersion;
159         DWORD dwFileVersionMS;
160         DWORD dwFileVersionLS;
161         DWORD dwProductVersionMS;
162         DWORD dwProductVersionLS;
163         DWORD dwFileFlagsMask;
164         DWORD dwFileFlags;
165         DWORD dwFileOS;
166         DWORD dwFileType;
167         DWORD dwFileSubtype;
168         DWORD dwFileDateMS;
169         DWORD dwFileDateLS;
170 };
171 struct VS_VERSIONINFO { struct VS_VERSIONINFO
172   WORD  wLength; 
173   WORD  wValueLength; 
174   WORD  wType; 
175   WCHAR szKey[1]; 
176   WORD  Padding1[1]; 
177   VS_FIXEDFILEINFO Value; 
178   WORD  Padding2[1]; 
179   WORD  Children[1]; 
180 };
181 [lib='kernel32.dll'] DWORD GetFileVersionInfoSizeA(char *szFileName, DWORD *dwVerHnd);
182 [lib='kernel32.dll'] int GetFileVersionInfoA(char *sfnFile, DWORD dummy, DWORD size, struct VS_VERSIONINFO *pVer);
183 ";
184             $ffi = new ffi($win32_idl);
185             $dummy = 0; // &DWORD
186             $size = $ffi->GetFileVersionInfoSizeA($file, $dummy);
187             //$pVer = str_repeat($size+1);
188             $pVer = new ffi_struct($ffi, "VS_VERSIONINFO");
189             if ($ffi->GetFileVersionInfoA($file, 0, $size, $pVer) 
190                 and $pVer->wValueLength) {
191                 // analyze the VS_FIXEDFILEINFO(Value);
192                 // $pValue = new ffi_struct($ffi, "VS_FIXEDFILEINFO");
193                 $pValue =& $pVer->Value;
194                 return sprintf("%d.%d.%d.%d",
195                                $pValue->dwFileVersionMS >> 16,
196                                $pValue->dwFileVersionMS & 0xFFFF,
197                                $pValue->dwFileVersionLS >> 16, 
198                                $pValue->dwFileVersionLS & 0xFFFF);
199             }
200         }
201     }
202
203     // Read "RT_VERSION/VERSIONINFO" exe/dll resource info for MSWin32 binaries
204     // The "win32std" extension is not ready yet to pass back a VERSIONINFO struct
205     function exeversion_resopen($file) {
206         if (function_exists('res_list_type') or loadPhpExtension('win32std')) {
207             // See http://msdn.microsoft.com/workshop/networking/predefined/res.asp
208             $v = file_get_contents('res://'.realpath($file).urlencode('/RT_VERSION/#1'));
209             if ($v) {
210                 // This is really a binary VERSIONINFO block, with lots of
211                 // nul bytes (widechar) which cannot be transported as string.
212                 return "$v";
213             }
214             else {
215                 $h = res_open(realpath($file));
216                 $v = res_get($h, 'RT_VERSION', 'FileVersion');
217                 res_close($h);
218                 if ($v) return $v;
219
220                 $h = res_open(realpath($file));
221                 $v = res_get($h, '#1', 'RT_VERSION', 1);
222                 res_close($h);
223                 if ($v) return $v;
224             }
225               
226             /* The version consists of two 32-bit integers, defined by four 16-bit integers. 
227                For example, "FILEVERSION 3,10,0,61" is translated into two doublewords: 
228                0x0003000a and 0x0000003d, in that order. */
229 /*          
230         $h = res_open(realpath($file));
231             
232         echo "Res list of '$file': \n";
233         $list= res_list_type($h, true);
234         if( $list===FALSE ) err( "Can't list type" );
235         
236         for( $i= 0; $i<count($list); $i++ ) {
237                 echo $list[$i]."\n";
238                 $res= res_list($h, $list[$i]);
239                 for( $j= 0; $j<count($res); $j++ ) {
240                         echo "\t".$res[$j]."\n";
241                 }
242         }
243         echo "Res get: ".res_get( $h, 'A_TYPE', 'A_RC_NAME' )."\n\n";
244         res_close( $h );            
245 */
246             if ($v)
247                 return "$v";
248             else 
249                 return "";
250         } else {
251             return "";
252         }
253         
254     }
255 };
256
257 // $Log: not supported by cvs2svn $
258
259 // For emacs users
260 // Local Variables:
261 // mode: php
262 // tab-width: 8
263 // c-basic-offset: 4
264 // c-hanging-comment-ender-p: nil
265 // indent-tabs-mode: nil
266 // End:
267 ?>