827
|
1 #!/usr/bin/php
|
|
2 <?
|
|
3 require_once "mconfig.inc.php";
|
|
4 require_once "msite.inc.php";
|
|
5
|
|
6 stCheckCLIExec();
|
|
7
|
|
8
|
912
|
9 function wtExec($exe, $args, $expect = 0)
|
902
|
10 {
|
|
11 echo "@@EXEC: ".$exe." ".$args."\n";
|
912
|
12 exec(escapeshellcmd($exe)." ".$args, $output, $code);
|
|
13 if ($code !== $expect)
|
902
|
14 {
|
912
|
15 echo
|
|
16 "Error executing ".$exe.": ".$code."\n".$args."\n".
|
|
17 "------------------------------------------------\n".
|
|
18 implode("\n", $output).
|
|
19 "------------------------------------------------\n";
|
902
|
20 return FALSE;
|
|
21 }
|
|
22 return TRUE;
|
|
23 }
|
|
24
|
912
|
25
|
882
|
26 function wtExecOrDie($exe, $args)
|
|
27 {
|
902
|
28 if (wtExec($exe, $args) === false)
|
|
29 die();
|
882
|
30 }
|
|
31
|
|
32
|
|
33 function wtConvertImage($inFilename, $inFileType, $outFilename, $setDim, $setFormat, $setQuality, $thumb)
|
|
34 {
|
|
35 global $setPreviewPath;
|
912
|
36 $isTemp = FALSE;
|
882
|
37
|
|
38 if (($outDim = stGetSetting($setDim)) === FALSE ||
|
|
39 ($outFormat = stGetSetting($osetFormat)) === FALSE ||
|
|
40 ($outQuality = stGetSetting($setQuality)) === FALSE)
|
|
41 {
|
|
42 die("Missing one of res/format/quality settings for '".$outFilename."'\n");
|
|
43 }
|
|
44
|
884
|
45 if ($inFileType == "gfx")
|
|
46 {
|
|
47 // Oh great .. we need gfxconv here because Imagick handles ILBM like shit
|
|
48 $filename = tempnam($setPreviewPath, "tmp");
|
912
|
49 $isTemp = TRUE;
|
|
50 if (wtExec(
|
884
|
51 "/usr/local/bin/gfxconv",
|
912
|
52 escapeshellarg($inFilename)." -f png -o ".escapeshellarg($filename)) === false)
|
|
53 return FALSE;
|
|
54
|
|
55 if (!file_exists($filename))
|
|
56 {
|
|
57 echo "ERROR: gfxconv did not output a temporary conversion inbetween.\n";
|
|
58 return FALSE;
|
|
59 }
|
|
60
|
884
|
61 }
|
|
62 else
|
|
63 $filename = $inFilename;
|
|
64
|
882
|
65 // convert -resize 640x480 -background black -gravity center -extent 640x480
|
|
66 // -unsharp "0x0.75+0.75+0.008" lol.lbm -quality 95 test.jpg
|
884
|
67
|
|
68 // Create conversion entity
|
|
69 $img = new Imagick($filename);
|
|
70 if ($img === false)
|
912
|
71 {
|
|
72 echo "ERROR: Oh noes! ImageMagick could not digest the file '".$filename."' (".$inFilename.")\n";
|
|
73 return FALSE;
|
|
74 }
|
884
|
75
|
|
76 // Get dimensions, setup background
|
|
77 $dim = $img->getImageGeometry();
|
|
78 $img->setBackgroundColor(imagick::COLOR_BLACK);
|
|
79 $img->setGravity(imagick::GRAVITY_CENTER);
|
|
80
|
|
81 // Act based on image size vs. desired size and $thumb mode
|
|
82 if ($thumb || $dim["width"] > $outDim[0] || $dim["height"] > $outDim[1])
|
|
83 {
|
|
84 // Image is larger
|
|
85 $img->resizeImage($outDim[0], $outDim[1], Imagick::FILTER_QUADRATIC, 1);
|
|
86 $img->setExtent($outDim[0], $outDim[1]);
|
|
87 $img->normalizeImage();
|
|
88 $img->unsharpMaskImage(0, 0.5, 1, 0.05);
|
|
89 }
|
|
90 else
|
|
91 if ($dim["width"] < $outDim[0] || $dim["height"] < $outDim[1])
|
|
92 {
|
|
93 // Image is smaller than requested dimension(s)?
|
|
94 $img->resizeImage($outDim[0], $outDim[1], Imagick::FILTER_POINT, 1);
|
|
95 $img->setExtent($outDim[0], $outDim[1]);
|
|
96 }
|
|
97
|
|
98 $img->setFormat($outFormat);
|
|
99 $img->setCompressionQuality($outQuality);
|
|
100
|
|
101 $img->stripImage();
|
|
102 $img->writeImage($outFilename);
|
|
103 $img->removeImage();
|
882
|
104 }
|
|
105
|
|
106
|
898
|
107 function wtRenderSample($inFilename, $outFilename)
|
882
|
108 {
|
898
|
109 $sfreq = intval(stGetSetting("sampleFreq"));
|
|
110 $sduration = intval(stGetSetting("sampleDuration"));
|
|
111 $schannels = intval(stGetSetting("sampleChannels"));
|
882
|
112
|
902
|
113 return wtExec(
|
898
|
114 "/usr/local/bin/openmpt123"
|
|
115 ,
|
884
|
116 "--quiet --render ".
|
|
117 "--samplerate ".$sfreq." ".
|
|
118 "--channels ".$schannels." ".
|
|
119 "--playtime ".$sduration." ".
|
898
|
120 escapeshellarg($inFilename)." -o ".escapeshellarg($outFilename));
|
882
|
121 }
|
|
122
|
|
123
|
898
|
124 function wtConvertSample($inFilename, $outFilename, $opts)
|
882
|
125 {
|
898
|
126 $sfreq = intval(stGetSetting("sampleFreq"));
|
|
127 $sduration = intval(stGetSetting("sampleDuration"));
|
|
128 $schannels = intval(stGetSetting("sampleChannels"));
|
882
|
129
|
898
|
130 foreach ($opts as $okey => $oval)
|
|
131 $optStr .= $okey." ".$oval." ";
|
|
132
|
902
|
133 return wtExec(
|
898
|
134 "/usr/local/bin/avconv",
|
|
135 "-y -t ".intval($sduration)." ".
|
|
136 "-i ".escapeshellarg($inFilename).
|
|
137 " ".$optStr." -ac ".$schannels.
|
|
138 " -map_metadata -1 ".
|
|
139 escapeshellarg($outFilename));
|
882
|
140 }
|
|
141
|
|
142
|
|
143 function wtPurgeDir($path)
|
|
144 {
|
|
145 if (file_exists($path))
|
|
146 wtExecOrDie("/bin/echo", "-fR ".escapeshellarg($path));
|
|
147 }
|
|
148
|
|
149
|
902
|
150 function wtUnpackArchiveTo($atype, $filename, $path)
|
882
|
151 {
|
|
152 // Check file type before doing anything
|
902
|
153 echo "Preparing to unpack archive file '".$filename."' ...\n";
|
|
154 switch ($atype)
|
882
|
155 {
|
|
156 case "LHA":
|
|
157 $exe = "/usr/bin/lha";
|
|
158 $args = "e ".escapeshellarg($filename);
|
|
159 break;
|
|
160
|
|
161 case "ZIP":
|
|
162 $exe = "/usr/bin/unzip";
|
|
163 $args = "-d ".escapeshellarg($path)." ".escapeshellarg($filename);
|
|
164 break;
|
|
165
|
898
|
166 case "RAR":
|
|
167 $exe = "/usr/bin/rar";
|
|
168 $args = "e ".escapeshellarg($filename);
|
|
169 break;
|
|
170
|
882
|
171 default:
|
902
|
172 echo "Unsupported archive file type: ".$atype."\n";
|
898
|
173 return FALSE;
|
882
|
174 }
|
|
175
|
|
176 // Create temporary directory
|
|
177 wtPurgeDir($path);
|
|
178 stMakeDir($path, 0700);
|
|
179
|
|
180 if (!is_dir($path) || chdir($path) === false)
|
902
|
181 {
|
|
182 echo "Failed to chdir to '".$path."', can't unpack archive.\n";
|
|
183 return FALSE;
|
|
184 }
|
882
|
185
|
|
186 // Unpack archive
|
902
|
187 return wtExec($exe, $args);
|
|
188 }
|
|
189
|
|
190
|
|
191 function wtScanArchive($efile, $filename)
|
|
192 {
|
|
193 global $setEntryPath;
|
|
194
|
|
195 $path = stMakePath(FALSE, FALSE, array($setEntryPath, "UNPACKS", $filename));
|
|
196
|
|
197 echo "Attempting to scan archive file '".$filename."' ...\n";
|
|
198
|
912
|
199 if (wtUnpackArchiveTo($efile["filetype"], $filename, $path) === false)
|
902
|
200 return FALSE;
|
882
|
201
|
|
202 // Scan through files ...
|
|
203 $dir = opendir($path);
|
|
204 while (($dentry = readdir($dir)) !== false)
|
|
205 {
|
|
206 }
|
|
207 closedir($dir);
|
|
208
|
|
209 wtPurgeDir($path);
|
902
|
210 return TRUE;
|
882
|
211 }
|
|
212
|
|
213
|
|
214 function wtHandleEntryPreview($compo, $entry, $mode)
|
|
215 {
|
898
|
216 // Get current preview file data
|
|
217 if (!stGetPreviewFileData($compo, $entry, $pdata))
|
|
218 return FALSE;
|
|
219
|
|
220 if ($entry["file_id"] != 0)
|
|
221 $efile = stFetchSQL("SELECT * FROM files WHERE deleted=0 AND id=".$entry["file_id"]);
|
|
222 else
|
|
223 $efile = FALSE;
|
|
224
|
|
225 // Check preview file(s) status
|
|
226 if ($mode == "sta")
|
|
227 {
|
|
228 printf(" %03d | %s%s%s | %-40s | %-5s | %s\n",
|
|
229 $entry["id"],
|
|
230 ($efile !== false) ? "1" : ".",
|
|
231 isset($pdata["file"]) ? "2" : ".",
|
|
232 $pdata["valid"] ? "3" : ".",
|
|
233 $entry["name"]." by ".$entry["author"],
|
|
234 isset($pdata["file"]) ? $pdata["file"]["filetype"] : "",
|
|
235 isset($pdata["file"]) ? $pdata["file"]["filename"] : ""
|
|
236 );
|
|
237 }
|
|
238 else
|
|
239 if ($mode == "upd")
|
|
240 {
|
882
|
241 /*
|
898
|
242 if (previewSourceFile does not exist)
|
882
|
243 {
|
|
244 if (entry is module file)
|
|
245 {
|
|
246 render sample
|
|
247 }
|
|
248 else
|
|
249 if (entry is image file)
|
|
250 {
|
|
251 convert image
|
|
252 }
|
898
|
253 else
|
|
254 if (entry is archive)
|
|
255 {
|
|
256 if compo preview type is image, scan archive for images ..
|
|
257 }
|
|
258 }
|
|
259
|
|
260 if (previewFiles older than previewSourceFile)
|
|
261 {
|
|
262 if (source == audio)
|
|
263 convert via avconv
|
|
264 else
|
|
265 if (source == image)
|
|
266 convert via imagick
|
882
|
267 }
|
|
268
|
|
269 // Based on compo / entry preview type ..
|
|
270
|
|
271 // Convert preview image file, if any
|
|
272 // Create thumbnail for it, too
|
|
273 wtConvertImage($inFilename, $outFilename,
|
|
274 "previewImageSize", "previewImageType",
|
|
275 "previewImageQuality", FALSE);
|
|
276
|
|
277 wtConvertImage($inFilename, $outFilename,
|
|
278 "previewThumbSize", "previewThumbType",
|
|
279 "previewThumbQuality", TRUE);
|
|
280 */
|
898
|
281 }
|
|
282 else
|
|
283 die("OMG!\n");
|
882
|
284 }
|
|
285
|
|
286
|
884
|
287 function wtHandleEntry($compo, $entry, $mode)
|
|
288 {
|
|
289 }
|
|
290
|
|
291
|
827
|
292 //
|
|
293 // Create directories
|
|
294 //
|
|
295 function stMakeDir($path, $perm)
|
|
296 {
|
|
297 if (!file_exists($path))
|
|
298 {
|
|
299 echo " - Creating ".$path."\n";
|
|
300 if (mkdir($path, $perm, TRUE) === false)
|
|
301 die("Could not create directory '".$path."'\n");
|
|
302 }
|
|
303 }
|
|
304
|
|
305
|
|
306 function stInitializeDirs()
|
|
307 {
|
902
|
308 global
|
|
309 $setEntryPath, $setPreviewPath, $setThumbDir,
|
827
|
310 $setEntryPathPerms, $setPrevPathPerms;
|
|
311
|
|
312 echo "Checking for missing directories ...\n";
|
|
313 stMakeDir($setEntryPath, $setEntryPathPerms);
|
|
314 stMakeDir($setPreviewPath, $setPrevPathPerms);
|
880
|
315 stMakeDir(stMakePath(FALSE, FALSE, array($setPreviewPath, $setThumbDir)), $setPrevPathPerms);
|
827
|
316
|
|
317 foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
|
|
318 {
|
|
319 stMakeDir(stMakePath(FALSE, FALSE, array($setEntryPath, $compo["cpath"])), $setEntryPathPerms);
|
|
320 }
|
|
321 }
|
|
322
|
|
323
|
|
324 //
|
|
325 // Main program starts
|
|
326 //
|
|
327 if ($argc < 2)
|
|
328 {
|
|
329 echo
|
|
330 "faptool - Do stuff with FAPWeb database\n".
|
|
331 "(C) Copyright 2014 ccr/TNSP\n".
|
|
332 "\n".
|
917
|
333 "Usage: ".$argv[0]." <command> [args]\n".
|
|
334 "Where command is one of following:\n".
|
827
|
335 "\n".
|
|
336 " init\n".
|
|
337 " Create directories for entries and previews, if needed.\n".
|
|
338 "\n".
|
917
|
339 " clean [delete|crap]\n".
|
|
340 " Clean files marked to be deleted and 'stale' files. This includes\n".
|
|
341 " any old or stale preview files and entry files.\n".
|
|
342 " Without 'delete' parameter just checks and shows what would deleted.\n".
|
|
343 " 'crap' parameter will purge EVERYTHING that is NOT in the database,\n".
|
|
344 " e.g. any other files, like temp files, etc. DANGEROUS IF YOU DO NOT\n".
|
|
345 " KNOW WHAT YOU ARE DOING!!!!!\n".
|
901
|
346 "\n".
|
881
|
347 " previews <cmd> [args]\n".
|
|
348 " Where <cmd> is one of:\n".
|
|
349 " status - List files and show what is missing, etc.\n".
|
901
|
350 "\n".
|
|
351 " entry <cmd> [args]\n".
|
|
352 " status - List entries for all compos.\n".
|
|
353 " unpack - Create subdirs and unpack archives under them.\n".
|
827
|
354 "\n";
|
|
355 exit;
|
|
356 }
|
|
357
|
|
358 // Try to connect to database
|
|
359 $spec = stGetSetting("sqlDB");
|
|
360 if (($db = stConnectSQLDBSpec($spec)) === false)
|
|
361 die("Could not connect to SQL database '".$spec."'.\n");
|
|
362
|
|
363 echo "Using database spec '".$spec."'.\n";
|
|
364
|
|
365 // Fetch non-"hardcoded" settings from SQL database
|
|
366 stReloadSettings();
|
|
367
|
|
368 // Set some globals for our benefit
|
900
|
369 $setWidth = 75;
|
827
|
370 $setEntryPath = stGetSetting("entryPath");
|
|
371 $setPreviewPath = stGetSetting("previewPath");
|
|
372 $setPreviewURL = stGetSetting("previewURL");
|
|
373 $setThumbDir = stGetSetting("thumbnailSubDir");
|
832
|
374 $setEntryPathPerms = stGetSetting("entryPathPerms");
|
|
375 $setPrevPathPerms = stGetSetting("previewPathPerms");
|
827
|
376
|
|
377 if ($setEntryPath === FALSE || $setPreviewPath === FALSE ||
|
832
|
378 $setPreviewURL === FALSE || $setThumbDir === FALSE ||
|
|
379 $setEntryPathPerms === FALSE || $setPrevPathPerms === FALSE)
|
827
|
380 {
|
831
|
381 die("Some required settings not defined in mconfig.inc.php!\n");
|
827
|
382 }
|
|
383
|
|
384
|
|
385 // Act according to specified command
|
884
|
386 switch (substr(stCArgLC(1), 0, 3))
|
827
|
387 {
|
884
|
388 case "ini":
|
827
|
389 //
|
|
390 // Initialize the data directories etc
|
|
391 //
|
|
392 stInitializeDirs();
|
|
393 break;
|
|
394
|
901
|
395 case "cle":
|
|
396 $doDelete = (stCArgLC(2) == "delete");
|
|
397 foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
|
|
398 if (stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo["id"]) > 0)
|
|
399 {
|
|
400 printf(
|
|
401 "==%'=-".($setWidth-2)."s\n".
|
|
402 sprintf("[ #%03d - %s ]", $compo["id"], substr($compo["name"], 0, 40))
|
|
403 );
|
|
404 echo str_repeat("-", $setWidth)."\n";
|
|
405
|
|
406 foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
|
|
407 {
|
|
408 foreach (stExecSQL("SELECT * FROM files WHERE entry_id=".$entry["id"]) as $efile)
|
|
409 {
|
|
410 if ($efile["delete"] != 0)
|
|
411 {
|
|
412 echo "X";
|
|
413 }
|
|
414 }
|
|
415 }
|
|
416 echo "\n";
|
|
417 echo str_repeat("-", $setWidth)."\n";
|
|
418 }
|
|
419 break;
|
|
420
|
|
421 case "ent":
|
|
422 //
|
|
423 // Entry files handling
|
|
424 //
|
|
425 $mode = substr(stCArgLC(2), 0, 3);
|
|
426 switch ($mode)
|
|
427 {
|
|
428 case "unp":
|
|
429 case "sta":
|
|
430 foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
|
|
431 if (stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo["id"]) > 0)
|
|
432 {
|
|
433 printf(
|
|
434 "==%'=-".($setWidth-2)."s\n".
|
|
435 sprintf("[ #%03d - %s ]", $compo["id"], substr($compo["name"], 0, 40))
|
|
436 );
|
|
437 echo str_repeat("-", $setWidth)."\n";
|
|
438
|
|
439 foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
|
|
440 wtHandleEntry($compo, $entry, $mode);
|
|
441
|
|
442 echo str_repeat("-", $setWidth)."\n";
|
|
443 }
|
|
444 break;
|
|
445
|
|
446 case "pac":
|
|
447 break;
|
|
448
|
|
449 case "add":
|
|
450 break;
|
|
451
|
|
452 default:
|
|
453 if ($mode == "")
|
|
454 die("ERROR! Entry command requires a sub-command argument.\n");
|
|
455 else
|
|
456 die("ERROR! Invalid entry sub-command '".stCArg(2)."'.\n");
|
|
457 break;
|
|
458 }
|
|
459 break;
|
|
460
|
884
|
461 case "pre":
|
881
|
462 //
|
|
463 // Preview files handling
|
|
464 //
|
|
465 $mode = substr(stCArgLC(2), 0, 3);
|
|
466 switch ($mode)
|
|
467 {
|
898
|
468 case "upd":
|
881
|
469 case "sta":
|
|
470 foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
|
898
|
471 if (stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo["id"]) > 0)
|
881
|
472 {
|
|
473 printf(
|
900
|
474 "==%'=-".($setWidth-2)."s\n".
|
898
|
475 "PrevType : %s\n",
|
|
476 sprintf("[ #%03d - %s ]", $compo["id"], substr($compo["name"], 0, 40)),
|
|
477 $previewTypeList[$compo["preview_type"]][0]);
|
|
478
|
|
479 printf(" %-3s | %-3s | %-40s |\n",
|
|
480 "#ID", "FLG", "Entry name/author");
|
|
481
|
900
|
482 echo str_repeat("-", $setWidth)."\n";
|
881
|
483
|
|
484 foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
|
|
485 wtHandleEntryPreview($compo, $entry, $mode);
|
898
|
486
|
900
|
487 echo str_repeat("=", $setWidth)."\n\n";
|
881
|
488 }
|
|
489 break;
|
|
490
|
901
|
491 case "add":
|
|
492 break;
|
|
493
|
881
|
494 default:
|
|
495 if ($mode == "")
|
|
496 die("ERROR! Previews command requires a sub-command argument.\n");
|
|
497 else
|
|
498 die("ERROR! Invalid previews sub-command '".stCArg(2)."'.\n");
|
|
499 break;
|
|
500 }
|
|
501 break;
|
|
502
|
827
|
503 default:
|
|
504 echo "ERROR! Invalid operation mode '".stCArg(1)."'.\n";
|
|
505 break;
|
|
506 }
|
|
507
|
|
508 ?> |