Passed
Push — 1.7 ( 4c1abf...23cbb7 )
by Greg
08:10
created

addmedia.php (2 issues)

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 33 and the first side effect is on line 23.

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.

Loading history...
2
/**
3
 * webtrees: online genealogy
4
 * Copyright (C) 2018 webtrees development team
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
 * GNU General Public License for more details.
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15
 */
16
namespace Fisharebest\Webtrees;
17
18
/**
19
 * Defined in session.php
20
 *
21
 * @global Tree $WT_TREE
22
 */
23
global $WT_TREE;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
24
25
use Fisharebest\Webtrees\Controller\SimpleController;
26
use Fisharebest\Webtrees\Functions\Functions;
27
use Fisharebest\Webtrees\Functions\FunctionsDb;
28
use Fisharebest\Webtrees\Functions\FunctionsEdit;
29
use Fisharebest\Webtrees\Functions\FunctionsImport;
30
use Fisharebest\Webtrees\Functions\FunctionsPrint;
31
use Fisharebest\Webtrees\Query\QueryMedia;
32
33
define('WT_SCRIPT_NAME', 'addmedia.php');
34
require './includes/session.php';
35
36
$NO_UPDATE_CHAN  = $WT_TREE->getPreference('NO_UPDATE_CHAN');
37
$MEDIA_DIRECTORY = $WT_TREE->getPreference('MEDIA_DIRECTORY');
38
39
$pid         = Filter::get('pid', WT_REGEX_XREF, Filter::post('pid', WT_REGEX_XREF)); // edit this media object
40
$linktoid    = Filter::get('linktoid', WT_REGEX_XREF, Filter::post('linktoid', WT_REGEX_XREF)); // create a new media object, linked to this record
41
$action      = Filter::get('action', null, Filter::post('action'));
42
$filename    = Filter::get('filename', null, Filter::post('filename'));
43
$text        = Filter::postArray('text');
44
$tag         = Filter::postArray('tag', WT_REGEX_TAG);
45
$islink      = Filter::postArray('islink');
46
$glevels     = Filter::postArray('glevels', '[0-9]');
47
$folder      = Filter::post('folder');
48
$update_CHAN = !Filter::postBool('preserve_last_changed');
49
50
$controller = new SimpleController;
51
$controller
52
	->addExternalJavascript(WT_AUTOCOMPLETE_JS_URL)
53
	->addInlineJavascript('autocomplete();')
54
	->restrictAccess(Auth::isMember($WT_TREE));
55
56
$disp  = true;
57
$media = Media::getInstance($pid, $WT_TREE);
58
if ($media) {
59
	$disp = $media->canShow();
60
}
61
if ($action == 'update' || $action == 'create') {
62
	if ($linktoid) {
63
		$disp = GedcomRecord::getInstance($linktoid, $WT_TREE)->canShow();
64
	}
65
}
66
67
if (!Auth::isEditor($WT_TREE) || !$disp) {
68
	$controller
69
		->pageHeader()
70
		->addInlineJavascript('closePopupAndReloadParent();');
71
72
	return;
73
}
74
75
// There is a lot of common code in the create and update cases…
76
// …and also in the admin_media_upload.php script
77
78
switch ($action) {
79
case 'create': // Save the information from the “showcreateform” action
80
	$controller->setPageTitle(I18N::translate('Create a media object'));
81
82
	// Validate the media folder
83
	$folderName = str_replace('\\', '/', $folder);
84
	$folderName = trim($folderName, '/');
85
	if ($folderName == '.') {
86
		$folderName = '';
87
	}
88
	if ($folderName) {
89
		$folderName .= '/';
90
		// Not allowed to use “../”
91
		if (strpos('/' . $folderName, '/../') !== false) {
92
			FlashMessages::addMessage('Folder names are not allowed to include “../”');
93
			break;
94
		}
95
	}
96
97
	// Make sure the media folder exists
98
	if (!is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
99
		if (File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
100
			FlashMessages::addMessage(I18N::translate('The folder %s has been created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)));
101
		} else {
102
			FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)), 'danger');
103
			break;
104
		}
105
	}
106
107
	// Managers can create new media paths (subfolders). Users must use existing folders.
108
	if ($folderName && !is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)) {
109
		if (Auth::isManager($WT_TREE)) {
110
			if (File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)) {
111
				FlashMessages::addMessage(I18N::translate('The folder %s has been created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)));
112
			} else {
113
				FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)), 'danger');
114
				break;
115
			}
116
		} else {
117
			// Regular users should not have seen this option - so no need for an error message.
118
			break;
119
		}
120
	}
121
122
	// The media folder exists. Now create a thumbnail folder to match it.
123
	if (!is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName)) {
124
		if (!File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName)) {
125
			FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName)), 'danger');
126
			break;
127
		}
128
	}
129
130
	// A thumbnail file with no main image?
131
	if (!empty($_FILES['thumbnail']['name']) && empty($_FILES['mediafile']['name'])) {
132
		// Assume the user used the wrong field, and treat this as a main image
133
		$_FILES['mediafile'] = $_FILES['thumbnail'];
134
		unset($_FILES['thumbnail']);
135
	}
136
137
	// Thumbnail files must contain images.
138
	if (!empty($_FILES['thumbnail']['name']) && !preg_match('/^image/', $_FILES['thumbnail']['type'])) {
139
		FlashMessages::addMessage(I18N::translate('Thumbnail files must contain images.'));
140
		break;
141
	}
142
143
	// User-specified filename?
144
	if ($tag[0] == 'FILE' && $text[0]) {
145
		$filename = $text[0];
146
	}
147
	// Use the name of the uploaded file?
148
	// If no filename specified, use the name of the uploaded file?
149
	if (!$filename && !empty($_FILES['mediafile']['name'])) {
150
		$filename = $_FILES['mediafile']['name'];
151
	}
152
153
	// Validate the media path and filename
154
	if (preg_match('/^https?:\/\//i', $text[0], $match)) {
155
		// External media needs no further validation
156
		$fileName   = $filename;
157
		$folderName = '';
158
		unset($_FILES['mediafile'], $_FILES['thumbnail']);
159
	} elseif (preg_match('/([\/\\\\<>])/', $filename, $match)) {
160
		// Local media files cannot contain certain special characters
161
		FlashMessages::addMessage(I18N::translate('Filenames are not allowed to contain the character “%s”.', $match[1]));
162
		break;
163
	} elseif (preg_match('/(\.(php|pl|cgi|bash|sh|bat|exe|com|htm|html|shtml))$/i', $filename, $match)) {
164
		// Do not allow obvious script files.
165
		FlashMessages::addMessage(I18N::translate('Filenames are not allowed to have the extension “%s”.', $match[1]));
166
		break;
167
	} elseif (!$filename) {
168
		FlashMessages::addMessage(I18N::translate('No media file was provided.'));
169
		break;
170
	} else {
171
		$fileName = $filename;
172
	}
173
174
	// Now copy the file to the correct location.
175
	if (!empty($_FILES['mediafile']['name'])) {
176
		$serverFileName = WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName . $fileName;
177
		if (file_exists($serverFileName)) {
178
			FlashMessages::addMessage(I18N::translate('The file %s already exists. Use another filename.', $folderName . $fileName));
179
			break;
180
		}
181
		if (move_uploaded_file($_FILES['mediafile']['tmp_name'], $serverFileName)) {
182
			Log::addMediaLog('Media file ' . $serverFileName . ' uploaded');
183
		} else {
184
			FlashMessages::addMessage(
185
				I18N::translate('There was an error uploading your file.') .
186
				'<br>' .
187
				Functions::fileUploadErrorText($_FILES['mediafile']['error'])
188
			);
189
			break;
190
		}
191
192
		// Now copy the (optional) thumbnail
193
		if (!empty($_FILES['thumbnail']['name']) && preg_match('/^image\/(png|gif|jpeg)/', $_FILES['thumbnail']['type'], $match)) {
194
			// Thumbnails have either
195
			// (a) the same filename as the main image
196
			// (b) the same filename as the main image - but with a .png extension
197
			if ($match[1] == 'png' && !preg_match('/\.(png)$/i', $fileName)) {
198
				$thumbFile = preg_replace('/\.[a-z0-9]{3,5}$/', '.png', $fileName);
199
			} else {
200
				$thumbFile = $fileName;
201
			}
202
			$serverFileName = WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName . $thumbFile;
203
			if (move_uploaded_file($_FILES['thumbnail']['tmp_name'], $serverFileName)) {
204
				Log::addMediaLog('Thumbnail file ' . $serverFileName . ' uploaded');
205
			}
206
		}
207
	}
208
209
	$controller->pageHeader();
210
	// Build the gedcom record
211
	$newged = "0 @new@ OBJE";
212
	if ($tag[0] == 'FILE') {
213
		// The admin has an edit field to change the filename
214
		$text[0] = $folderName . $fileName;
215
	} else {
216
		// Users keep the original filename
217
		$newged .= "\n1 FILE " . $folderName . $fileName;
218
	}
219
220
	$newged = FunctionsEdit::handleUpdates($newged);
221
222
	$new_media = $WT_TREE->createRecord($newged);
223
	if ($linktoid) {
224
		$record = GedcomRecord::getInstance($linktoid, $WT_TREE);
225
		$record->createFact('1 OBJE @' . $new_media->getXref() . '@', true);
226
		Log::addEditLog('Media ID ' . $new_media->getXref() . " successfully added to $linktoid.");
227
		$controller->addInlineJavascript('closePopupAndReloadParent();');
228
	} else {
229
		Log::addEditLog('Media ID ' . $new_media->getXref() . ' successfully added.');
230
		$controller->addInlineJavascript('openerpasteid("' . $new_media->getXref() . '");');
231
	}
232
	echo '<button onclick="closePopupAndReloadParent();">', I18N::translate('close'), '</button>';
233
234
	return;
235
236
case 'update': // Save the information from the “editmedia” action
237
	$controller->setPageTitle(I18N::translate('Edit the media object'));
238
239
	// Validate the media folder
240
	$folderName = str_replace('\\', '/', $folder);
241
	$folderName = trim($folderName, '/');
242
	if ($folderName == '.') {
243
		$folderName = '';
244
	}
245
	if ($folderName) {
246
		$folderName .= '/';
247
		// Not allowed to use “../”
248
		if (strpos('/' . $folderName, '/../') !== false) {
249
			FlashMessages::addMessage('Folder names are not allowed to include “../”');
250
			break;
251
		}
252
	}
253
254
	// Make sure the media folder exists
255
	if (!is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
256
		if (File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
257
			FlashMessages::addMessage(I18N::translate('The folder %s has been created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)));
258
		} else {
259
			FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)), 'danger');
260
			break;
261
		}
262
	}
263
264
	// Managers can create new media paths (subfolders). Users must use existing folders.
265
	if ($folderName && !is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)) {
266
		if (Auth::isManager($WT_TREE)) {
267
			if (File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)) {
268
				FlashMessages::addMessage(I18N::translate('The folder %s has been created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)));
269
			} else {
270
				FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY . $folderName)), 'danger');
271
				break;
272
			}
273
		} else {
274
			// Regular users should not have seen this option - so no need for an error message.
275
			break;
276
		}
277
	}
278
279
	// The media folder exists. Now create a thumbnail folder to match it.
280
	if (!is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName)) {
281
		if (!File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName)) {
282
			FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY . 'thumbs/' . $folderName)), 'danger');
283
			break;
284
		}
285
	}
286
287
	// Validate the media path and filename
288
	if (preg_match('/^https?:\/\//i', $filename, $match)) {
289
		// External media needs no further validation
290
		$fileName   = $filename;
291
		$folderName = '';
292
		unset($_FILES['mediafile'], $_FILES['thumbnail']);
293
	} elseif (preg_match('/([\/\\\\<>])/', $filename, $match)) {
294
		// Local media files cannot contain certain special characters
295
		FlashMessages::addMessage(I18N::translate('Filenames are not allowed to contain the character “%s”.', $match[1]));
296
		break;
297
	} elseif (preg_match('/(\.(php|pl|cgi|bash|sh|bat|exe|com|htm|html|shtml))$/i', $filename, $match)) {
298
		// Do not allow obvious script files.
299
		FlashMessages::addMessage(I18N::translate('Filenames are not allowed to have the extension “%s”.', $match[1]));
300
		break;
301
	} elseif (!$filename) {
302
		FlashMessages::addMessage(I18N::translate('No media file was provided.'));
303
		break;
304
	} else {
305
		$fileName = $filename;
306
	}
307
308
	$oldFilename = $media->getFilename();
309
	$newFilename = $folderName . $fileName;
310
311
	// Cannot rename local to external or vice-versa
312
	if (Functions::isFileExternal($oldFilename) != Functions::isFileExternal($filename)) {
313
		FlashMessages::addMessage(I18N::translate('The media file %1$s could not be renamed to %2$s.', Html::filename($oldFilename), Html::filename($newFilename)));
314
		break;
315
	}
316
317
	$messages  = false;
318
	$move_file = false;
319
320
	// Move files on disk (if we can) to reflect the change to the GEDCOM data
321
	if (!$media->isExternal()) {
322
		$oldServerFile  = $media->getServerFilename('main');
323
		$oldServerThumb = $media->getServerFilename('thumb');
324
325
		$newmedia       = new Media("xxx", "0 @xxx@ OBJE\n1 FILE " . $newFilename, null, $WT_TREE);
326
		$newServerFile  = $newmedia->getServerFilename('main');
327
		$newServerThumb = $newmedia->getServerFilename('thumb');
328
329
		// We could be either renaming an existing file, or updating a record (with no valid file) to point to a new file
330
		if ($oldServerFile !== $newServerFile) {
331
			//-- check if the file is used in more than one gedcom
332
			//-- do not allow it to be moved or renamed if it is
333
			if (!$media->isExternal() && FunctionsDb::isMediaUsedInOtherTree($media->getFilename(), $WT_TREE->getTreeId())) {
334
				FlashMessages::addMessage(I18N::translate('This file is linked to another family tree on this server. It cannot be deleted, moved, or renamed until these links have been removed.'));
335
				break;
336
			}
337
338
			$move_file = true;
339
			if (!file_exists($newServerFile) || md5_file($oldServerFile) === md5_file($newServerFile)) {
340
				try {
341
					rename($oldServerFile, $newServerFile);
342
					FlashMessages::addMessage(I18N::translate('The media file %1$s has been renamed to %2$s.', Html::filename($oldFilename), Html::filename($newFilename)));
343
				} catch (\ErrorException $ex) {
344
					FlashMessages::addMessage(I18N::translate('The media file %1$s could not be renamed to %2$s.', Html::filename($oldFilename), Html::filename($newFilename)));
345
				}
346
				$messages = true;
347
			}
348
			if (!file_exists($newServerFile)) {
349
				FlashMessages::addMessage(I18N::translate('The media file %s does not exist.', Html::filename($newFilename)));
350
				$messages = true;
351
			}
352
		}
353
		if ($oldServerThumb != $newServerThumb) {
354
			$move_file = true;
355
			if (!file_exists($newServerThumb) || md5_file($oldServerFile) == md5_file($newServerThumb)) {
356
				try {
357
					rename($oldServerThumb, $newServerThumb);
358
					FlashMessages::addMessage(I18N::translate('The thumbnail file %1$s has been renamed to %2$s.', Html::filename($oldFilename), Html::filename($newFilename)));
359
				} catch (\ErrorException $ex) {
360
					FlashMessages::addMessage(I18N::translate('The thumbnail file %1$s could not be renamed to %2$s.', Html::filename($oldFilename), Html::filename($newFilename)));
361
				}
362
				$messages = true;
363
			}
364
			if (!file_exists($newServerThumb)) {
365
				FlashMessages::addMessage(I18N::translate('The thumbnail file %s does not exist.', Html::filename($newFilename)));
366
				$messages = true;
367
			}
368
		}
369
	}
370
371
	// Insert the 1 FILE xxx record into the arrays used by function FunctionsEdit::handle_updatesges()
372
	$glevels = array_merge(array('1'), $glevels);
373
	$tag     = array_merge(array('FILE'), $tag);
374
	$islink  = array_merge(array(0), $islink);
375
	$text    = array_merge(array($newFilename), $text);
376
377
	$record = GedcomRecord::getInstance($pid, $WT_TREE);
378
	$newrec = "0 @$pid@ OBJE\n";
379
	$newrec = FunctionsEdit::handleUpdates($newrec);
380
	$record->updateRecord($newrec, $update_CHAN);
381
382
	if ($move_file) {
383
		// We've moved a file. Therefore we must approve the change, as rejecting
384
		// the change will create broken references.
385
		FunctionsImport::acceptAllChanges($record->getXref(), $record->getTree()->getTreeId());
386
	}
387
388
	if ($pid && $linktoid) {
389
		$record = GedcomRecord::getInstance($linktoid, $WT_TREE);
390
		$record->createFact('1 OBJE @' . $pid . '@', true);
391
		Log::addEditLog('Media ID ' . $pid . " successfully added to $linktoid.");
392
	}
393
	$controller->pageHeader();
394
	if ($messages) {
395
		echo '<button onclick="closePopupAndReloadParent();">', I18N::translate('close'), '</button>';
396
	} else {
397
		$controller->addInlineJavascript('closePopupAndReloadParent();');
398
	}
399
400
	return;
401
case 'showmediaform':
402
	$controller->setPageTitle(I18N::translate('Create a media object'));
403
	$action = 'create';
404
	break;
405
case 'editmedia':
406
	$controller->setPageTitle(I18N::translate('Edit the media object'));
407
	$action = 'update';
408
	break;
409
default:
410
	throw new \Exception('Bad $action (' . $action . ') in addmedia.php');
411
}
412
413
$controller->pageHeader();
414
415
echo '<div id="addmedia-page">'; //container for media edit pop-up
416
echo '<form method="post" name="newmedia" action="addmedia.php" enctype="multipart/form-data">';
417
echo '<input type="hidden" name="action" value="', $action, '">';
418
echo '<input type="hidden" name="ged" value="', $WT_TREE->getNameHtml(), '">';
419
echo '<input type="hidden" name="pid" value="', $pid, '">';
420
if ($linktoid) {
421
	echo '<input type="hidden" name="linktoid" value="', $linktoid, '">';
422
}
423
echo '<table class="facts_table">';
424
echo '<tr><td class="topbottombar" colspan="2">';
425
echo $controller->getPageTitle(), FunctionsPrint::helpLink('OBJE');
426
echo '</td></tr>';
427
if (!$linktoid && $action == 'create') {
428
	echo '<tr><td class="descriptionbox wrap width25">';
429
	echo I18N::translate('Enter an individual, family, or source ID');
430
	echo '</td><td class="optionbox wrap"><input type="text" data-autocomplete-type="IFS" name="linktoid" id="linktoid" size="6" value="">';
431
	echo ' ', FunctionsPrint::printFindIndividualLink('linktoid');
432
	echo ' ', FunctionsPrint::printFindFamilyLink('linktoid');
433
	echo ' ', FunctionsPrint::printFindSourceLink('linktoid');
434
	echo '<p class="small text-muted">', I18N::translate('Enter or search for the ID of the individual, family, or source to which this media object should be linked.'), '</p></td></tr>';
435
}
436
437
if ($media) {
438
	$gedrec = $media->getGedcom();
439
} else {
440
	$gedrec = '';
441
}
442
443
// 1 FILE
444
if (preg_match('/\n\d (FILE.*)/', $gedrec, $match)) {
445
	$gedfile = $match[1];
446
} elseif ($filename) {
447
	$gedfile = 'FILE ' . $filename;
448
} else {
449
	$gedfile = 'FILE';
450
}
451
452
if ($gedfile == 'FILE') {
453
	// Box for user to choose to upload file from local computer
454
	echo '<tr><td class="descriptionbox wrap width25">';
455
	echo I18N::translate('Media file to upload') . '</td><td class="optionbox wrap"><input type="file" name="mediafile" onchange="updateFormat(this.value);" size="40"></td></tr>';
456
	// Check for thumbnail generation support
457
	if (Auth::isManager($WT_TREE)) {
458
		echo '<tr><td class="descriptionbox wrap width25">';
459
		echo I18N::translate('Thumbnail to upload') . '</td><td class="optionbox wrap"><input type="file" name="thumbnail" size="40">';
460
		echo '<p class="small text-muted">', I18N::translate('Choose the thumbnail image that you want to upload. Although thumbnails can be generated automatically for images, you may wish to generate your own thumbnail, especially for other media types. For example, you can provide a still image from a video, or a photograph of the individual who made an audio recording.'), '</p>';
461
		echo '</td></tr>';
462
	}
463
}
464
465
// Filename on server
466
$isExternal = Functions::isFileExternal($gedfile);
467
if ($gedfile == 'FILE') {
468
	if (Auth::isManager($WT_TREE)) {
469
		FunctionsEdit::addSimpleTag(
470
			"1 $gedfile",
471
			'',
472
			I18N::translate('Filename on server'),
473
			'<p class="small text-muted">' . I18N::translate('Do not change to keep original filename.') . '<br>' . I18N::translate('You may enter a URL, beginning with “http://”.') . '</p>'
474
		);
475
	}
476
	$folder = '';
477
} else {
478
	if ($isExternal) {
479
		$fileName = substr($gedfile, 5);
480
		$folder   = '';
481
	} else {
482
		$tmp      = substr($gedfile, 5);
483
		$fileName = basename($tmp);
484
		$folder   = dirname($tmp);
485
		if ($folder === '.') {
486
			$folder = '';
487
		}
488
	}
489
490
	echo '<tr>';
491
	echo '<td class="descriptionbox wrap width25">';
492
	echo I18N::translate('Filename on server');
493
	echo '</td>';
494
	echo '<td class="optionbox wrap wrap">';
495
	if (Auth::isManager($WT_TREE)) {
496
		echo '<input name="filename" type="text" value="' . Filter::escapeHtml($fileName) . '" size="40"';
497
		if ($isExternal) {
498
			echo '>';
499
		} else {
500
			echo '><p class="small text-muted">' . I18N::translate('Do not change to keep original filename.') . '</p>';
501
		}
502
	} else {
503
		echo $fileName;
504
		echo '<input name="filename" type="hidden" value="' . Filter::escapeHtml($fileName) . '" size="40">';
505
	}
506
	echo '</td>';
507
	echo '</tr>';
508
}
509
510
// Box for user to choose the folder to store the image
511
if (!$isExternal) {
512
	echo '<tr><td class="descriptionbox wrap width25">';
513
	echo I18N::translate('Folder name on server'), '</td><td class="optionbox wrap">';
514
	//-- don’t let regular users change the location of media items
515
	if ($action !== 'update' || Auth::isManager($WT_TREE)) {
516
		$mediaFolders = QueryMedia::folderList();
517
		echo '<select name="folder_list" onchange="document.newmedia.folder.value=this.options[this.selectedIndex].value;">';
518
		echo '<option ';
519
		if ($folder == '') {
520
			echo 'selected';
521
		}
522
		echo ' value=""> ', I18N::translate('Choose: '), ' </option>';
523
		if (Auth::isAdmin()) {
524
			echo '<option value="other" disabled>', I18N::translate('Other folder… please type in'), "</option>";
525
		}
526
		foreach ($mediaFolders as $f) {
527
			echo '<option value="', $f, '" ';
528
			if ($folder == $f) {
529
				echo 'selected';
530
			}
531
			echo '>', $f, "</option>";
532
		}
533
		echo '</select>';
534
	} else {
535
		echo $folder;
536
	}
537
	if (Auth::isAdmin()) {
538
		echo '<br><input type="text" name="folder" size="40" value="', $folder, '">';
539
		if ($gedfile === 'FILE') {
540
			echo '<p class="small text-muted">', I18N::translate('This entry is ignored if you have entered a URL into the filename field.'), '</p>';
541
		}
542
	} else {
543
		echo '<input name="folder" type="hidden" value="', Filter::escapeHtml($folder), '">';
544
	}
545
	echo '<p class="small text-muted">', I18N::translate('If you have a large number of media files, you can organize them into folders and subfolders.'), '</p>'; echo '</td></tr>';
546
} else {
547
	echo '<input name="folder" type="hidden" value="">';
548
}
549
550
// 1 FILE / 2 FORM
551
if (preg_match('/\n(2 FORM .*)/', $gedrec, $match)) {
552
	$gedform = $match[1];
553
} else {
554
	$gedform = '2 FORM';
555
}
556
$formid = FunctionsEdit::addSimpleTag($gedform);
557
558
// automatically set the format field from the filename
559
$controller->addInlineJavascript('
560
	function updateFormat(filename) {
561
		var extsearch=/\.([a-zA-Z]{3,4})$/;
562
		if (extsearch.exec(filename)) {
563
			ext = RegExp.$1.toLowerCase();
564
			if (ext=="jpg") ext="jpeg";
565
			if (ext=="tif") ext="tiff";
566
		} else {
567
			ext = "";
568
		}
569
		formfield = document.getElementById("' . $formid . '");
570
		formfield.value = ext;
571
	}
572
');
573
574
// 1 FILE / 2 FORM / 3 TYPE
575
if (preg_match('/\n(3 TYPE .*)/', $gedrec, $match)) {
576
	$gedtype = $match[1];
577
} else {
578
	$gedtype = '3 TYPE photo'; // default to ‘Photo’
579
}
580
FunctionsEdit::addSimpleTag($gedtype);
581
582
// 1 FILE / 2 TITL
583
if (preg_match('/\n(2 TITL .*)/', $gedrec, $match)) {
584
	$gedtitl = $match[1];
585
} else {
586
	$gedtitl = '2 TITL';
587
}
588
FunctionsEdit::addSimpleTag($gedtitl);
589
590
// 1 FILE / 2 TITL / 3 _HEB
591
if (strstr($WT_TREE->getPreference('ADVANCED_NAME_FACTS'), '_HEB') !== false) {
592
	if (preg_match('/\n(3 _HEB .*)/', $gedrec, $match)) {
593
		$gedtitl = $match[1];
594
	} else {
595
		$gedtitl = '3 _HEB';
596
	}
597
	FunctionsEdit::addSimpleTag($gedtitl);
598
}
599
600
// 1 FILE / 2 TITL / 3 ROMN
601
if (strstr($WT_TREE->getPreference('ADVANCED_NAME_FACTS'), 'ROMN') !== false) {
602
	if (preg_match('/\n(3 ROMN .*)/', $gedrec, $match)) {
603
		$gedtitl = $match[1];
604
	} else {
605
		$gedtitl = '3 ROMN';
606
	}
607
	FunctionsEdit::addSimpleTag($gedtitl);
608
}
609
610
// 1 _PRIM
611
if (preg_match('/\n(1 _PRIM .*)/', $gedrec, $match)) {
612
	$gedprim = $match[1];
613
} else {
614
	$gedprim = '1 _PRIM';
615
}
616
FunctionsEdit::addSimpleTag($gedprim);
617
618
//-- print out editing fields for any other data in the media record
619
$sourceLevel = 0;
620
$sourceSOUR  = '';
621
$sourcePAGE  = '';
622
$sourceTEXT  = '';
623
$sourceDATE  = '';
624
$sourceQUAY  = '';
625
if (!empty($gedrec)) {
626
	preg_match_all('/\n(1 (?!FILE|FORM|TYPE|TITL|_PRIM|_THUM|CHAN|DATA).*(\n[2-9] .*)*)/', $gedrec, $matches);
627
	foreach ($matches[1] as $subrec) {
628
		$pieces = explode("\n", $subrec);
629
		foreach ($pieces as $piece) {
630
			$ft = preg_match("/(\d) (\w+)(.*)/", $piece, $match);
631
			if ($ft == 0) {
632
				continue;
633
			}
634
			$subLevel = $match[1];
635
			$fact     = trim($match[2]);
636
			$event    = trim($match[3]);
637
			if ($fact === 'NOTE' || $fact === 'TEXT') {
638
				$event .= Functions::getCont($subLevel + 1, $subrec);
639
			}
640
			if ($sourceSOUR !== '' && $subLevel <= $sourceLevel) {
641
				// Get rid of all saved Source data
642
				FunctionsEdit::addSimpleTag($sourceLevel . ' SOUR ' . $sourceSOUR);
643
				FunctionsEdit::addSimpleTag(($sourceLevel + 1) . ' PAGE ' . $sourcePAGE);
644
				FunctionsEdit::addSimpleTag(($sourceLevel + 2) . ' TEXT ' . $sourceTEXT);
645
				FunctionsEdit::addSimpleTag(($sourceLevel + 2) . ' DATE ' . $sourceDATE, '', GedcomTag::getLabel('DATA:DATE'));
646
				FunctionsEdit::addSimpleTag(($sourceLevel + 1) . ' QUAY ' . $sourceQUAY);
647
				$sourceSOUR = '';
648
			}
649
650
			if ($fact === 'SOUR') {
651
				$sourceLevel = $subLevel;
652
				$sourceSOUR  = $event;
653
				$sourcePAGE  = '';
654
				$sourceTEXT  = '';
655
				$sourceDATE  = '';
656
				$sourceQUAY  = '';
657
				continue;
658
			}
659
660
			// Save all incoming data about this source reference
661
			if ($sourceSOUR !== '') {
662
				if ($fact === 'PAGE') {
663
					$sourcePAGE = $event;
664
					continue;
665
				}
666
				if ($fact === 'TEXT') {
667
					$sourceTEXT = $event;
668
					continue;
669
				}
670
				if ($fact === 'DATE') {
671
					$sourceDATE = $event;
672
					continue;
673
				}
674
				if ($fact === 'QUAY') {
675
					$sourceQUAY = $event;
676
					continue;
677
				}
678
				continue;
679
			}
680
681
			// Output anything that isn’t part of a source reference
682
			if (!empty($fact) && $fact !== 'CONC' && $fact !== 'CONT' && $fact !== 'DATA') {
683
				FunctionsEdit::addSimpleTag($subLevel . ' ' . $fact . ' ' . $event);
684
			}
685
		}
686
	}
687
688
	if ($sourceSOUR !== '') {
689
		// Get rid of all saved Source data
690
		FunctionsEdit::addSimpleTag($sourceLevel . ' SOUR ' . $sourceSOUR);
691
		FunctionsEdit::addSimpleTag(($sourceLevel + 1) . ' PAGE ' . $sourcePAGE);
692
		FunctionsEdit::addSimpleTag(($sourceLevel + 2) . ' TEXT ' . $sourceTEXT);
693
		FunctionsEdit::addSimpleTag(($sourceLevel + 2) . ' DATE ' . $sourceDATE, '', GedcomTag::getLabel('DATA:DATE'));
694
		FunctionsEdit::addSimpleTag(($sourceLevel + 1) . ' QUAY ' . $sourceQUAY);
695
	}
696
}
697
if (Auth::isAdmin() && $action === 'update') {
698
	echo '<tr><td class="descriptionbox wrap width25">';
699
	echo GedcomTag::getLabel('CHAN'), '</td><td class="optionbox wrap">';
700
	if ($NO_UPDATE_CHAN) {
701
		echo '<input type="checkbox" checked name="preserve_last_changed">';
702
	} else {
703
		echo '<input type="checkbox" name="preserve_last_changed">';
704
	}
705
	echo I18N::translate('Keep the existing “last change” information'), '<br>';
706
	echo '</td></tr>';
707
}
708
echo '</table>';
709
FunctionsEdit::printAddLayer('SOUR', 1);
710
FunctionsEdit::printAddLayer('NOTE', 1);
711
FunctionsEdit::printAddLayer('SHARED_NOTE', 1);
712
FunctionsEdit::printAddLayer('RESN', 1);
713
?>
714
		<p id="save-cancel">
715
			<input type="submit" class="save" value="<?php echo I18N::translate('save'); ?>">
716
			<input type="button" class="cancel" value="<?php echo I18N::translate('close'); ?>" onclick="window.close();">
717
		</p>
718
	</form>
719
</div>
720