1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/*************************************************************************** |
3
|
|
|
* For license information see doc/license.txt |
4
|
|
|
* |
5
|
|
|
* Unicode Reminder メモ |
6
|
|
|
* |
7
|
|
|
* get/set has to be commited with save |
8
|
|
|
* add/remove etc. is executed instantly |
9
|
|
|
***************************************************************************/ |
10
|
|
|
|
11
|
|
|
require_once __DIR__ . '/const.inc.php'; |
12
|
|
|
|
13
|
|
|
class picture |
|
|
|
|
14
|
|
|
{ |
15
|
|
|
public $nPictureId = 0; |
16
|
|
|
public $rePicture; |
17
|
|
|
public $sFileExtension = ''; |
18
|
|
|
public $bFilenamesSet = false; |
19
|
|
|
|
20
|
|
|
public static function pictureIdFromUUID($uuid) |
21
|
|
|
{ |
22
|
|
|
return sql_value("SELECT `id` FROM `pictures` WHERE `uuid`='&1'", 0, $uuid); |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
public static function fromUUID($uuid) |
26
|
|
|
{ |
27
|
|
|
$pictureId = picture::pictureIdFromUUID($uuid); |
28
|
|
|
if ($pictureId == 0) { |
29
|
|
|
return null; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
return new picture($pictureId); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
public function __construct($nNewPictureId = ID_NEW) |
36
|
|
|
{ |
37
|
|
|
global $opt; |
38
|
|
|
|
39
|
|
|
$this->rePicture = new rowEditor('pictures'); |
40
|
|
|
$this->rePicture->addPKInt('id', null, false, RE_INSERT_AUTOINCREMENT); |
41
|
|
|
$this->rePicture->addString('uuid', '', false, RE_INSERT_AUTOUUID); |
42
|
|
|
$this->rePicture->addInt('node', 0, false); |
43
|
|
|
$this->rePicture->addDate('date_created', time(), true, RE_INSERT_IGNORE); |
44
|
|
|
$this->rePicture->addDate('last_modified', time(), true, RE_INSERT_IGNORE); |
45
|
|
|
$this->rePicture->addString('url', '', false); |
46
|
|
|
$this->rePicture->addString('title', '', false); |
47
|
|
|
$this->rePicture->addDate('last_url_check', 0, true); |
48
|
|
|
$this->rePicture->addInt('object_id', null, false); |
49
|
|
|
$this->rePicture->addInt('object_type', null, false); |
50
|
|
|
$this->rePicture->addString('thumb_url', '', false); |
51
|
|
|
$this->rePicture->addDate('thumb_last_generated', 0, false); |
52
|
|
|
$this->rePicture->addInt('spoiler', 0, false); |
53
|
|
|
$this->rePicture->addInt('local', 0, false); |
54
|
|
|
$this->rePicture->addInt('unknown_format', 0, false); |
55
|
|
|
$this->rePicture->addInt('display', 1, false); |
56
|
|
|
$this->rePicture->addInt('mappreview', 0, false); |
57
|
|
|
$this->rePicture->addInt('seq', 0, false); |
58
|
|
|
|
59
|
|
|
$this->nPictureId = $nNewPictureId + 0; |
60
|
|
|
|
61
|
|
|
if ($nNewPictureId == ID_NEW) { |
62
|
|
|
$this->rePicture->addNew(null); |
63
|
|
|
|
64
|
|
|
$sUUID = mb_strtoupper(sql_value("SELECT UUID()", '')); |
65
|
|
|
$this->rePicture->setValue('uuid', $sUUID); |
66
|
|
|
$this->rePicture->setValue('node', $opt['logic']['node']['id']); |
67
|
|
|
} else { |
68
|
|
|
$this->rePicture->load($this->nPictureId); |
69
|
|
|
|
70
|
|
|
$sFilename = $this->getFilename(); |
71
|
|
|
$fna = mb_split('\\.', $sFilename); |
72
|
|
|
$this->sFileExtension = mb_strtolower($fna[count($fna) - 1]); |
73
|
|
|
|
74
|
|
|
$this->bFilenamesSet = true; |
75
|
|
|
} |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
public function exist() |
79
|
|
|
{ |
80
|
|
|
return $this->rePicture->exist(); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
public static function allowedExtension($sFilename) |
84
|
|
|
{ |
85
|
|
|
global $opt; |
86
|
|
|
|
87
|
|
|
if (strpos($sFilename, ';') !== false) { |
88
|
|
|
return false; |
89
|
|
|
} |
90
|
|
|
if (strpos($sFilename, '.') === false) { |
91
|
|
|
return false; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
$sExtension = mb_strtolower(substr($sFilename, strrpos($sFilename, '.') + 1)); |
95
|
|
|
|
96
|
|
|
if (strpos(';' . $opt['logic']['pictures']['extensions'] . ';', ';' . $sExtension . ';') !== false) { |
97
|
|
|
return true; |
98
|
|
|
} else { |
99
|
|
|
return false; |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* @param string $sFilename |
105
|
|
|
*/ |
106
|
|
|
public function setFilenames($sFilename) |
107
|
|
|
{ |
108
|
|
|
global $opt; |
109
|
|
|
|
110
|
|
|
if ($this->bFilenamesSet == true) { |
|
|
|
|
111
|
|
|
return; |
112
|
|
|
} |
113
|
|
|
if (strpos($sFilename, '.') === false) { |
114
|
|
|
return; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$sExtension = mb_strtolower(substr($sFilename, strrpos($sFilename, '.') + 1)); |
118
|
|
|
$this->sFileExtension = $sExtension; |
119
|
|
|
|
120
|
|
|
$sUUID = $this->getUUID(); |
121
|
|
|
|
122
|
|
|
$this->setUrl($opt['logic']['pictures']['url'] . $sUUID . '.' . $sExtension); |
123
|
|
|
//$this->setThumbUrl($opt['logic']['pictures']['thumb_url'] . substr($sUUID, 0, 1) . '/' . substr($sUUID, 1, 1) . '/' . $sUUID . '.' . $sExtension); |
|
|
|
|
124
|
|
|
|
125
|
|
|
$this->bFilenamesSet = true; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
public function getPictureId() |
129
|
|
|
{ |
130
|
|
|
return $this->nPictureId; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* @param boolean $bRestoring |
135
|
|
|
*/ |
136
|
|
|
private function setArchiveFlag($bRestoring, $original_id = 0) |
137
|
|
|
{ |
138
|
|
|
global $login; |
139
|
|
|
|
140
|
|
|
// This function determines if an insert, update oder deletion at pictures table |
141
|
|
|
// ist to be recorded for vandalism recovery, depending on WHO OR WHY the |
142
|
|
|
// operation is done. Other conditions, depending on the data, are handled |
143
|
|
|
// by triggers. |
144
|
|
|
// |
145
|
|
|
// Data is passed by ugly global DB variables, so try call this function as |
146
|
|
|
// close before the targetet DB operation as possible. |
147
|
|
|
|
148
|
|
|
if ($this->getObjectType() == 1) { |
149
|
|
|
/* |
|
|
|
|
150
|
|
|
$owner_id = sql_value("SELECT `user_id` FROM `caches` WHERE `cache_id`= |
151
|
|
|
IFNULL((SELECT `cache_id` FROM `cache_logs` WHERE `id`='&1'), |
152
|
|
|
(SELECT `cache_id` FROM `cache_logs_archived` WHERE `id`='&1'))", |
153
|
|
|
0, $this->getObjectId()); |
154
|
|
|
*/ |
155
|
|
|
$logger_id = sql_value( |
156
|
|
|
"SELECT |
157
|
|
|
IFNULL((SELECT `user_id` FROM `cache_logs` WHERE `id`='&1'), |
158
|
|
|
(SELECT `user_id` FROM `cache_logs_archived` WHERE `id`='&1'))", |
159
|
|
|
0, |
160
|
|
|
$this->getObjectId() |
161
|
|
|
); |
162
|
|
|
$archive = ($bRestoring || $login->userid != $logger_id); |
163
|
|
|
} else { |
164
|
|
|
$archive = true; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
sql("SET @archive_picop=" . ($archive ? "TRUE" : "FALSE")); |
168
|
|
|
sql_slave("SET @archive_picop=" . ($archive ? "TRUE" : "FALSE")); |
169
|
|
|
|
170
|
|
|
sql("SET @original_picid='&1'", $original_id); |
171
|
|
|
sql_slave("SET @original_picid='&1'", $original_id); |
172
|
|
|
|
173
|
|
|
// @archive_picop and @original_picid are evaluated by trigger functions |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
private function resetArchiveFlag() |
177
|
|
|
{ |
178
|
|
|
sql("SET @archive_picop=FALSE"); |
179
|
|
|
sql("SET @original_picid=0"); |
180
|
|
|
sql_slave("SET @archive_picop=FALSE"); |
181
|
|
|
sql_slave("SET @original_picid=0"); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @return string |
186
|
|
|
*/ |
187
|
|
|
public function getUrl() |
188
|
|
|
{ |
189
|
|
|
return $this->rePicture->getValue('url'); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* @param string $value |
194
|
|
|
*/ |
195
|
|
|
public function setUrl($value) |
196
|
|
|
{ |
197
|
|
|
return $this->rePicture->setValue('url', $value); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
public function getThumbUrl() |
201
|
|
|
{ |
202
|
|
|
return $this->rePicture->getValue('thumb_url'); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
public function setThumbUrl($value) |
206
|
|
|
{ |
207
|
|
|
return $this->rePicture->setValue('thumb_url', $value); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
public function getTitle() |
211
|
|
|
{ |
212
|
|
|
return $this->rePicture->getValue('title'); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
public function setTitle($value) |
216
|
|
|
{ |
217
|
|
|
if ($value != '') { |
218
|
|
|
return $this->rePicture->setValue('title', $value); |
219
|
|
|
} else { |
220
|
|
|
return false; |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
public function getSpoiler() |
225
|
|
|
{ |
226
|
|
|
return $this->rePicture->getValue('spoiler') != 0; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
public function setSpoiler($value) |
230
|
|
|
{ |
231
|
|
|
return $this->rePicture->setValue('spoiler', $value ? 1 : 0); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
public function getLocal() |
235
|
|
|
{ |
236
|
|
|
return $this->rePicture->getValue('local') != 0; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* @param integer $value |
241
|
|
|
*/ |
242
|
|
|
public function setLocal($value) |
243
|
|
|
{ |
244
|
|
|
return $this->rePicture->setValue('local', $value ? 1 : 0); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
public function getUnknownFormat() |
248
|
|
|
{ |
249
|
|
|
return $this->rePicture->getValue('unknown_format') != 0; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
public function setUnknownFormat($value) |
253
|
|
|
{ |
254
|
|
|
return $this->rePicture->setValue('unknown_format', $value ? 1 : 0); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
public function getDisplay() |
258
|
|
|
{ |
259
|
|
|
return $this->rePicture->getValue('display') != 0; |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
public function setDisplay($value) |
263
|
|
|
{ |
264
|
|
|
return $this->rePicture->setValue('display', $value ? 1 : 0); |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
public function getMapPreview() |
268
|
|
|
{ |
269
|
|
|
return $this->rePicture->getValue('mappreview') != 0; |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
public function setMapPreview($value) |
273
|
|
|
{ |
274
|
|
|
return $this->rePicture->setValue('mappreview', $value ? 1 : 0); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
public function getFilename() |
278
|
|
|
{ |
279
|
|
|
// works intendently before bFilenameSet == true ! |
280
|
|
|
global $opt; |
281
|
|
|
|
282
|
|
View Code Duplication |
if (mb_substr($opt['logic']['pictures']['dir'], -1, 1) != '/') { |
283
|
|
|
$opt['logic']['pictures']['dir'] .= '/'; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
$url = $this->getUrl(); |
287
|
|
|
$fna = mb_split('\\/', $url); |
288
|
|
|
|
289
|
|
|
return $opt['logic']['pictures']['dir'] . end($fna); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
public function getThumbFilename() |
293
|
|
|
{ |
294
|
|
|
global $opt; |
295
|
|
|
|
296
|
|
View Code Duplication |
if (mb_substr($opt['logic']['pictures']['thumb_dir'], -1, 1) != '/') { |
297
|
|
|
$opt['logic']['pictures']['thumb_dir'] .= '/'; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
$url = $this->getUrl(); |
301
|
|
|
$fna = mb_split('\\/', $url); |
302
|
|
|
$filename = end($fna); |
303
|
|
|
|
304
|
|
|
$dir1 = mb_strtoupper(mb_substr($filename, 0, 1)); |
305
|
|
|
$dir2 = mb_strtoupper(mb_substr($filename, 1, 1)); |
306
|
|
|
|
307
|
|
|
return $opt['logic']['pictures']['thumb_dir'] . $dir1 . '/' . $dir2 . '/' . $filename; |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* @return string |
312
|
|
|
*/ |
313
|
|
|
public function getLogId() |
314
|
|
|
{ |
315
|
|
|
if ($this->getObjectType() == OBJECT_CACHELOG) { |
316
|
|
|
return $this->getObjectId(); |
317
|
|
|
} else { |
318
|
|
|
return false; |
|
|
|
|
319
|
|
|
} |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
public function isVisibleOnCachePage() |
323
|
|
|
{ |
324
|
|
|
if ($this->getObjectType() != OBJECT_CACHELOG) { |
325
|
|
|
return null; |
326
|
|
|
} else { |
327
|
|
|
$rs = sql( |
328
|
|
|
"SELECT `id` |
329
|
|
|
FROM `cache_logs` |
330
|
|
|
WHERE `cache_id`='&1' |
331
|
|
|
ORDER BY `date`, `id` DESC |
332
|
|
|
LIMIT &2", |
333
|
|
|
$this->getCacheId(), |
334
|
|
|
MAX_LOGENTRIES_ON_CACHEPAGE |
335
|
|
|
); |
336
|
|
|
} |
337
|
|
|
$firstlogs = false; |
338
|
|
|
while ($r = sql_fetch_assoc($rs)) { |
339
|
|
|
if ($r['id'] == $this->getLogId()) { |
340
|
|
|
$firstlogs = true; |
341
|
|
|
} |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
sql_free_result($rs); |
345
|
|
|
|
346
|
|
|
return $firstlogs; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* @return string |
351
|
|
|
*/ |
352
|
|
View Code Duplication |
public function getCacheId() |
|
|
|
|
353
|
|
|
{ |
354
|
|
|
if ($this->getObjectType() == OBJECT_CACHELOG) { |
355
|
|
|
return sql_value("SELECT `cache_id` FROM `cache_logs` WHERE `id`='&1'", false, $this->getObjectId()); |
356
|
|
|
} elseif ($this->getObjectType() == OBJECT_CACHE) { |
357
|
|
|
return $this->getObjectId(); |
358
|
|
|
} else { |
359
|
|
|
return false; |
|
|
|
|
360
|
|
|
} |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
public function getObjectId() |
364
|
|
|
{ |
365
|
|
|
return $this->rePicture->getValue('object_id'); |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
public function setObjectId($value) |
369
|
|
|
{ |
370
|
|
|
return $this->rePicture->setValue('object_id', $value + 0); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
public function getObjectType() |
374
|
|
|
{ |
375
|
|
|
return $this->rePicture->getValue('object_type'); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
public function setObjectType($value) |
379
|
|
|
{ |
380
|
|
|
return $this->rePicture->setValue('object_type', $value + 0); |
381
|
|
|
} |
382
|
|
|
|
383
|
|
View Code Duplication |
public function getUserId() |
|
|
|
|
384
|
|
|
{ |
385
|
|
|
if ($this->getObjectType() == OBJECT_CACHE) { |
386
|
|
|
return sql_value( |
387
|
|
|
"SELECT `caches`.`user_id` FROM `caches` WHERE `caches`.`cache_id`='&1'", |
388
|
|
|
false, |
389
|
|
|
$this->getObjectId() |
390
|
|
|
); |
391
|
|
|
} elseif ($this->getObjectType() == OBJECT_CACHELOG) { |
392
|
|
|
return sql_value( |
393
|
|
|
"SELECT `cache_logs`.`user_id` FROM `cache_logs` WHERE `cache_logs`.`id`='&1'", |
394
|
|
|
false, |
395
|
|
|
$this->getObjectId() |
396
|
|
|
); |
397
|
|
|
} else { |
398
|
|
|
return false; |
399
|
|
|
} |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
public function getNode() |
403
|
|
|
{ |
404
|
|
|
return $this->rePicture->getValue('node'); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
public function setNode($value) |
408
|
|
|
{ |
409
|
|
|
return $this->rePicture->setValue('node', $value); |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
public function getUUID() |
413
|
|
|
{ |
414
|
|
|
return $this->rePicture->getValue('uuid'); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
public function getLastModified() |
418
|
|
|
{ |
419
|
|
|
return $this->rePicture->getValue('last_modified'); |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
public function getDateCreated() |
423
|
|
|
{ |
424
|
|
|
return $this->rePicture->getValue('date_created'); |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
public function getPosition() |
428
|
|
|
{ |
429
|
|
|
return $this->rePicture->getValue('seq'); |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
public function getAnyChanged() |
433
|
|
|
{ |
434
|
|
|
return $this->rePicture->getAnyChanged(); |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
// Test if the picture can be discarded as duplicate. |
438
|
|
|
// This is a quick test for Ocprop dups and may be extended for any |
439
|
|
|
// picture uploads by comparing the file sizes and contents. |
440
|
|
|
|
441
|
|
|
public function is_duplicate() |
442
|
|
|
{ |
443
|
|
|
global $ocpropping; |
444
|
|
|
|
445
|
|
|
return $ocpropping && |
446
|
|
|
sql_value( |
447
|
|
|
" |
448
|
|
|
SELECT COUNT(*) FROM `pictures` |
449
|
|
|
WHERE `object_type`='&1' AND `object_id`='&2' AND `title`='&3'", |
450
|
|
|
0, |
451
|
|
|
$this->getObjectType(), |
452
|
|
|
$this->getObjectId(), |
453
|
|
|
$this->getTitle() |
454
|
|
|
) > 0; |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
// return true if successful (with insert) |
|
|
|
|
458
|
|
|
public function save($restore = false, $original_id = 0, $original_url = "") |
459
|
|
|
{ |
460
|
|
|
$undelete = ($original_id != 0); |
461
|
|
|
|
462
|
|
|
if ($undelete) { |
463
|
|
|
if ($this->bFilenamesSet == true) { |
|
|
|
|
464
|
|
|
return false; |
465
|
|
|
} else { |
466
|
|
|
// restore picture file |
467
|
|
|
$this->setUrl($original_url); // set the url, so that we can |
468
|
|
|
$filename = $this->getFilename(); // .. retrieve the file path+name |
469
|
|
|
$this->setFilenames($filename); // now set url(s) from the new uuid |
470
|
|
|
try { |
471
|
|
|
rename($this->deletedFilename($filename), $this->getFilename()); |
|
|
|
|
472
|
|
|
} catch (Exception $e) { |
473
|
|
|
// @todo implement logging |
474
|
|
|
} |
475
|
|
|
} |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
if ($this->bFilenamesSet == false) { |
|
|
|
|
479
|
|
|
return false; |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
$this->setArchiveFlag($restore, $original_id); |
483
|
|
|
$bRetVal = $this->rePicture->save(); |
484
|
|
|
$this->resetArchiveFlag(); |
485
|
|
|
|
486
|
|
|
if ($bRetVal) { |
487
|
|
|
$this->nPictureId = $this->rePicture->getValue('id'); |
488
|
|
|
if ($this->getObjectType() == OBJECT_CACHE && $this->getMapPreview()) { |
489
|
|
|
sql( |
490
|
|
|
"UPDATE `pictures` SET `mappreview`= 0 |
491
|
|
|
WHERE `object_type`='&1' AND `object_id`='&2' AND `id`!='&3'", |
492
|
|
|
OBJECT_CACHE, |
493
|
|
|
$this->getObjectId(), |
494
|
|
|
$this->getPictureId() |
495
|
|
|
); |
496
|
|
|
} |
497
|
|
|
sql_slave_exclude(); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
return $bRetVal; |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
public function delete($restore = false) |
504
|
|
|
{ |
505
|
|
|
// see also removelog.php, 'remove log pictures' |
506
|
|
|
|
507
|
|
|
global $opt; |
508
|
|
|
|
509
|
|
|
// delete record, image and thumb |
510
|
|
|
$this->setArchiveFlag($restore); |
511
|
|
|
sql("DELETE FROM `pictures` WHERE `id`='&1'", $this->nPictureId); |
512
|
|
|
$this->resetArchiveFlag(); |
513
|
|
|
$filename = $this->getFilename(); |
514
|
|
|
|
515
|
|
|
// archive picture if picture record has been archived |
516
|
|
|
if (sql_value("SELECT `id` FROM `pictures_modified` WHERE `id`='&1'", 0, $this->getPictureId()) != 0) { |
517
|
|
|
try { |
518
|
|
|
rename($filename, $this->deletedFilename($filename)); |
|
|
|
|
519
|
|
|
} catch (Exception $e) { |
520
|
|
|
// @todo implement logging |
521
|
|
|
} |
522
|
|
|
} else { |
523
|
|
|
try { |
524
|
|
|
unlink($filename); |
|
|
|
|
525
|
|
|
} catch (Exception $e) { |
526
|
|
|
// @todo implement logging |
527
|
|
|
} |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
try { |
531
|
|
|
unlink($this->getThumbFilename()); |
|
|
|
|
532
|
|
|
} catch (Exception $e) { |
533
|
|
|
// @todo implement logging |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
return true; |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
/** |
540
|
|
|
* @param string $filename |
541
|
|
|
* |
542
|
|
|
* @return string |
543
|
|
|
*/ |
544
|
|
|
private function deletedFilename($filename) |
545
|
|
|
{ |
546
|
|
|
$fna = mb_split('\\/', $filename); |
547
|
|
|
$fna[] = end($fna); |
548
|
|
|
$fna[count($fna) - 2] = 'deleted'; |
549
|
|
|
$dp = ''; |
550
|
|
|
foreach ($fna as $fp) { |
551
|
|
|
$dp .= '/' . $fp; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
return substr($dp, 1); |
555
|
|
|
} |
556
|
|
|
|
557
|
|
View Code Duplication |
public function allowEdit() |
|
|
|
|
558
|
|
|
{ |
559
|
|
|
global $login; |
560
|
|
|
|
561
|
|
|
$login->verify(); |
562
|
|
|
|
563
|
|
|
if (sql_value( |
564
|
|
|
"SELECT COUNT(*) |
565
|
|
|
FROM `caches` |
566
|
|
|
INNER JOIN `cache_status` ON `caches`.`status`=`cache_status`.`id` |
567
|
|
|
WHERE (`cache_status`.`allow_user_view`=1 OR `caches`.`user_id`='&1') |
568
|
|
|
AND `caches`.`cache_id`='&2'", 0, $login->userid, $this->getCacheId() |
569
|
|
|
) == 0 |
570
|
|
|
) { |
571
|
|
|
return false; |
572
|
|
|
} elseif ($this->getUserId() == $login->userid) { |
573
|
|
|
return true; |
574
|
|
|
} |
575
|
|
|
|
576
|
|
|
return false; |
577
|
|
|
} |
578
|
|
|
|
579
|
|
|
public function getPageLink() |
580
|
|
|
{ |
581
|
|
|
if ($this->getObjectType() == OBJECT_CACHELOG) { |
582
|
|
|
$pl = 'viewcache.php?cacheid=' . urlencode($this->getCacheId()); |
583
|
|
|
if (!$this->isVisibleOnCachePage()) { |
|
|
|
|
584
|
|
|
$pl .= "&log=A"; |
585
|
|
|
} |
586
|
|
|
$pl .= "#log" . urlencode($this->getLogId()); |
587
|
|
|
} elseif ($this->getObjectType() == OBJECT_CACHE) { |
588
|
|
|
$pl = 'editcache.php?cacheid=' . urlencode($this->getCacheId()) . '#pictures'; |
589
|
|
|
} else { |
590
|
|
|
$pl = false; |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
return $pl; |
594
|
|
|
} |
595
|
|
|
|
596
|
|
|
/* |
597
|
|
|
Shrink picture to a specified maximum size. If present Imagemagick extension will be used, if not gd. |
598
|
|
|
Imagick is sharper, faster, need less memory and supports more types. |
599
|
|
|
For gd size is limited to 5000px (memory consumption). |
600
|
|
|
i prefer FILTER_CATROM because its faster but similiar to lanczos see http://de1.php.net/manual/de/imagick.resizeimage.php |
601
|
|
|
parameter: |
602
|
|
|
$tmpfile: full name of uploaded file |
603
|
|
|
$longSideSize: if longer side of picture > $longSideSize, then it will be prop. shrinked to |
604
|
|
|
returns: true if no error occur, otherwise false |
605
|
|
|
*/ |
606
|
|
|
public function rotate_and_shrink($tmpFile, $longSideSize) |
607
|
|
|
{ |
608
|
|
|
global $opt; |
609
|
|
|
if (extension_loaded('imagick')) { |
610
|
|
|
try { |
611
|
|
|
$image = new Imagick(); |
612
|
|
|
$image->readImage($tmpFile); |
613
|
|
|
$this->imagick_rotate($image); |
614
|
|
|
$w = $image->getImageWidth(); |
615
|
|
|
$h = $image->getImageHeight(); |
616
|
|
|
$image->setImageResolution(PICTURE_RESOLUTION, PICTURE_RESOLUTION); |
617
|
|
|
$image->setImageCompression(Imagick::COMPRESSION_JPEG); |
618
|
|
|
$image->setImageCompressionQuality(PICTURE_QUALITY); |
619
|
|
|
$image->stripImage(); //clears exif, private data |
620
|
|
|
//$newSize=$w<$h?array($w*$longSideSize/$h,$longSideSize):array($longSideSize,$h*$longSideSize/$w); |
|
|
|
|
621
|
|
|
if (max($w, $h) > $longSideSize) { |
622
|
|
|
$image->resizeImage($longSideSize, $longSideSize, imagick::FILTER_CATROM, 1, true); |
623
|
|
|
} |
624
|
|
|
$result = $image->writeImage($this->getFilename()); |
625
|
|
|
$image->clear(); |
626
|
|
|
} catch (Exception $e) { |
627
|
|
|
if ($image) { |
628
|
|
|
$image->clear(); |
629
|
|
|
} |
630
|
|
|
if ($opt['debug'] & DEBUG_DEVELOPER) { |
631
|
|
|
die($e); |
|
|
|
|
632
|
|
|
} |
633
|
|
|
$result = false; |
634
|
|
|
} |
635
|
|
|
|
636
|
|
|
return $result; |
637
|
|
|
} elseif (extension_loaded('gd')) { |
638
|
|
|
$imageNew = null; |
639
|
|
|
try { |
640
|
|
|
$image = imagecreatefromstring(file_get_contents($tmpFile)); |
641
|
|
|
$w = imagesx($image); |
642
|
|
|
$h = imagesy($image); |
643
|
|
|
if (max($w, $h) > 5000) { |
644
|
|
|
throw new Exception("Image too large >5000px"); |
645
|
|
|
} |
646
|
|
|
if (max($w, $h) <= $longSideSize) { |
647
|
|
|
$result = imagejpeg($image, $this->getFilename(), PICTURE_QUALITY); |
648
|
|
|
} else { |
649
|
|
|
$newSize = $w < $h ? [ |
650
|
|
|
$w * $longSideSize / $h, |
651
|
|
|
$longSideSize |
652
|
|
|
] : [ |
653
|
|
|
$longSideSize, |
654
|
|
|
$h * $longSideSize / $w |
655
|
|
|
]; |
656
|
|
|
$imageNew = imagecreatetruecolor($newSize[0], $newSize[1]); |
657
|
|
|
imagecopyresampled($imageNew, $image, 0, 0, 0, 0, $newSize[0], $newSize[1], $w, $h); |
658
|
|
|
$result = imagejpeg($imageNew, $this->getFilename(), PICTURE_QUALITY); |
659
|
|
|
imagedestroy($imageNew); |
660
|
|
|
} |
661
|
|
|
imagedestroy($image); |
662
|
|
|
} catch (Exception $e) { |
663
|
|
|
if ($image) { |
664
|
|
|
imagedestroy($image); |
665
|
|
|
} |
666
|
|
|
if ($imageNew) { |
667
|
|
|
imagedestroy($imageNew); |
668
|
|
|
} |
669
|
|
|
if ($opt['debug'] & DEBUG_DEVELOPER) { |
670
|
|
|
die($e); |
|
|
|
|
671
|
|
|
} |
672
|
|
|
$result = false; |
673
|
|
|
} |
674
|
|
|
|
675
|
|
|
return $result; |
676
|
|
|
} else { |
677
|
|
|
return false; |
678
|
|
|
} |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
// rotate image according to EXIF orientation |
682
|
|
|
public function rotate($tmpFile) |
683
|
|
|
{ |
684
|
|
|
if (extension_loaded('imagick')) { |
685
|
|
|
try { |
686
|
|
|
$image = new Imagick(); |
687
|
|
|
$image->readImage($tmpFile); |
688
|
|
|
if ($this->imagick_rotate($image)) { |
689
|
|
|
$image->stripImage(); // clears exif, private data |
690
|
|
|
$image->writeImage($this->getFilename()); |
691
|
|
|
$image->clear(); |
692
|
|
|
|
693
|
|
|
return true; |
694
|
|
|
} else { |
695
|
|
|
$image->clear(); |
696
|
|
|
} |
697
|
|
|
} catch (Exception $e) { |
698
|
|
|
if ($image) { |
699
|
|
|
$image->clear(); |
700
|
|
|
} |
701
|
|
|
} |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
return move_uploaded_file($tmpFile, $this->getFilename()); |
|
|
|
|
705
|
|
|
} |
706
|
|
|
|
707
|
|
|
/** |
708
|
|
|
* @param Imagick $image |
709
|
|
|
* |
710
|
|
|
* @return bool |
711
|
|
|
*/ |
712
|
|
|
public function imagick_rotate(&$image) |
713
|
|
|
{ |
714
|
|
|
$exif = $image->getImageProperties(); |
715
|
|
|
if (isset($exif['exif:Orientation'])) { |
716
|
|
|
switch ($exif['exif:Orientation']) { |
717
|
|
|
case 3: |
718
|
|
|
return $image->rotateImage(new ImagickPixel(), 180); |
719
|
|
|
case 6: |
720
|
|
|
return $image->rotateImage(new ImagickPixel(), 90); |
721
|
|
|
case 8: |
722
|
|
|
return $image->rotateImage(new ImagickPixel(), -90); |
723
|
|
|
} |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
return false; |
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
public function up() |
730
|
|
|
{ |
731
|
|
|
$prevPos = sql_value( |
732
|
|
|
" |
733
|
|
|
SELECT MAX(`seq`) |
734
|
|
|
FROM `pictures` |
735
|
|
|
WHERE `object_type`='&1' AND `object_id`='&2' AND `seq`<'&3'", |
736
|
|
|
0, |
737
|
|
|
$this->getObjectType(), |
738
|
|
|
$this->getObjectId(), |
739
|
|
|
$this->getPosition() |
740
|
|
|
); |
741
|
|
|
|
742
|
|
|
if ($prevPos) { |
743
|
|
|
$maxPos = sql_value( |
744
|
|
|
" |
745
|
|
|
SELECT MAX(`seq`) |
746
|
|
|
FROM `pictures` |
747
|
|
|
WHERE `object_type`='&1' AND `object_id`='&2'", |
748
|
|
|
0, |
749
|
|
|
$this->getObjectType(), |
750
|
|
|
$this->getObjectId() |
751
|
|
|
); |
752
|
|
|
|
753
|
|
|
// swap positions with the previous pic |
754
|
|
|
sql( |
755
|
|
|
" |
756
|
|
|
UPDATE `pictures` |
757
|
|
|
SET `seq`='&2' |
758
|
|
|
WHERE `id`='&1'", |
759
|
|
|
$this->getPictureId(), |
760
|
|
|
$maxPos + 1 |
761
|
|
|
); |
762
|
|
|
sql( |
763
|
|
|
" |
764
|
|
|
UPDATE `pictures` SET `seq`='&4' |
765
|
|
|
WHERE `object_type`='&1' AND `object_id`='&2' AND `seq`='&3'", |
766
|
|
|
$this->getObjectType(), |
767
|
|
|
$this->getObjectId(), |
768
|
|
|
$prevPos, |
769
|
|
|
$this->getPosition() |
770
|
|
|
); |
771
|
|
|
sql( |
772
|
|
|
" |
773
|
|
|
UPDATE `pictures` |
774
|
|
|
SET `seq`='&2' |
775
|
|
|
WHERE `id`='&1'", |
776
|
|
|
$this->getPictureId(), |
777
|
|
|
$prevPos |
778
|
|
|
); |
779
|
|
|
$this->rePicture->setValue('seq', $prevPos); |
780
|
|
|
|
781
|
|
|
return true; |
782
|
|
|
} |
783
|
|
|
|
784
|
|
|
return false; |
785
|
|
|
} |
786
|
|
|
} |
787
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.