Subversion Repositories oidplus

Rev

Rev 1109 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
647 daniel-mar 1
#!/usr/bin/env php
2
<?php
3
 
4
/*
5
 * OIDplus 2.0
797 daniel-mar 6
 * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft
647 daniel-mar 7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
 
21
// This script will be called at the ViaThinkSoft server side
22
 
651 daniel-mar 23
// Generate keypair with:
24
//	openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:8192
25
//	openssl rsa -pubout -in private.pem -out public.pem
26
 
647 daniel-mar 27
$argc = $_SERVER['argc']; // to please Eclipse for PHP
28
$argv = $_SERVER['argv']; // to please Eclipse for PHP
29
 
30
if (PHP_SAPI != 'cli') {
663 daniel-mar 31
	fwrite(STDERR, "This file can only be invoked in CLI mode.\n");
32
	die();
647 daniel-mar 33
}
34
 
718 daniel-mar 35
if (DIRECTORY_SEPARATOR != '/') {
36
	echo "This script can only run on Unix like systems\n";
37
	exit(2);
38
}
39
 
651 daniel-mar 40
if ($argc != 4) {
41
	echo "Usage: ".$argv[0]." <targetpath> <privkey> <force(1|0)>\n";
647 daniel-mar 42
	exit(2);
43
}
44
 
45
$output_dir = $argv[1];
651 daniel-mar 46
$priv_key = $argv[2];
47
$force = $argv[3];
647 daniel-mar 48
 
49
if (!is_dir($output_dir)) {
50
	echo "Path $output_dir does not exist!\n";
51
	exit(1);
52
}
53
 
718 daniel-mar 54
if (!is_file($priv_key)) {
651 daniel-mar 55
	echo "Private key file $priv_key does not exist!\n";
56
	exit(1);
57
}
58
 
59
if (($force != '1') && ($force != '0')) {
60
	echo "Argument 'force' must be 0 or 1\n";
61
	exit(1);
62
}
63
 
647 daniel-mar 64
$outscript = '';
663 daniel-mar 65
$func_idx = 0;
647 daniel-mar 66
 
718 daniel-mar 67
 
68
// First, write the change scripts
69
 
70
$out = array();
71
$ec = -1;
72
exec('svn info https://svn.viathinksoft.com/svn/oidplus/trunk/ | grep "Revision:" | cut -d " " -f 2', $out, $ec);
73
if ($ec != 0) die("SVN Info failed!!!\n");
74
$max_svn = implode("", $out);
75
 
76
for ($i=2; $i<=$max_svn; $i++) {
77
	echo "SVN revision $i / $max_svn\r";
78
 
79
	$outfile = $output_dir."/update_".($i-1)."_to_$i.txt";
80
	if (!$force && is_file($outfile)) continue;
81
 
82
	$outdir_old = "/tmp/oidplus_svntmp2_".($i-1)."/";
83
	if ($outdir_old && is_dir($outdir_old)) exec("rm -rf $outdir_old", $out, $ec);
84
	exec("svn co https://svn.viathinksoft.com/svn/oidplus/trunk/@".($i-1)." $outdir_old", $out, $ec);
85
	if ($ec != 0) die("Checkout of SVN Rev ".($i-1)." failed!!!\n");
86
	hotfix_dir($i-1, $outdir_old);
87
 
88
	$outdir_new = "/tmp/oidplus_svntmp2_$i/";
89
	if ($outdir_new && is_dir($outdir_new)) exec("rm -rf $outdir_new", $out, $ec);
90
	exec("svn co https://svn.viathinksoft.com/svn/oidplus/trunk/@$i $outdir_new", $out, $ec);
91
	if ($ec != 0) die("Checkout of SVN Rev ".($i)." failed!!!\n");
92
	hotfix_dir($i, $outdir_new);
93
 
94
	$outscript  = "<?php\n";
95
	$outscript .= "\n";
96
	$outscript .= "/*\n";
97
	$outscript .= " * OIDplus 2.0\n";
98
	$outscript .= " * Copyright 2019 - ".date('Y')." Daniel Marschall, ViaThinkSoft\n";
99
	$outscript .= " *\n";
100
	$outscript .= " * Licensed under the Apache License, Version 2.0 (the \"License\");\n";
101
	$outscript .= " * you may not use this file except in compliance with the License.\n";
102
	$outscript .= " * You may obtain a copy of the License at\n";
103
	$outscript .= " *\n";
104
	$outscript .= " *     http://www.apache.org/licenses/LICENSE-2.0\n";
105
	$outscript .= " *\n";
106
	$outscript .= " * Unless required by applicable law or agreed to in writing, software\n";
107
	$outscript .= " * distributed under the License is distributed on an \"AS IS\" BASIS,\n";
108
	$outscript .= " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n";
109
	$outscript .= " * See the License for the specific language governing permissions and\n";
110
	$outscript .= " * limitations under the License.\n";
111
	$outscript .= " */\n";
112
	$outscript .= "\n";
113
	$outscript .= "function info(\$str) { echo \"INFO: \$str\\n\"; }\n";
114
	$outscript .= "function warn(\$str) { echo \"WARNING: \$str\\n\"; }\n";
115
	$outscript .= "function err(\$str) { die(\"FATAL ERROR: \$str\\n\"); }\n";
116
	$outscript .= "\n";
117
	$outscript .= "@set_time_limit(0);\n";
118
	$outscript .= "\n";
119
	$outscript .= "@header('Content-Type: text/plain');\n";
120
	$outscript .= "\n";
121
	$outscript .= "chdir(__DIR__);\n";
122
	if ($i >= 662) {
123
		$outscript .= "if (trim(@file_get_contents('.version.php')) !== '<?php // Revision ".($i-1)."') {\n";
124
		$outscript .= "\terr('This update can only be applied to OIDplus version svn-".($i-1)."!');\n";
125
		$outscript .= "}\n";
126
	} else {
127
		$outscript .= "if (trim(@file_get_contents('oidplus_version.txt')) !== 'Revision ".($i-1)."') {\n";
128
		$outscript .= "\terr('This update can only be applied to OIDplus version svn-".($i-1)."!');\n";
129
		$outscript .= "}\n";
130
	}
131
	$outscript .= "\n";
132
	/*
133
	if ($i >= 99999) {
134
		... once we require PHP 7.1, we add the requirement here
135
		... also if we require fancy new PHP modules, we must add it here
136
		... the checks avoid that someone breaks their OIDplus installation if they update
137
	} else
138
	*/if ($i >= 2) {
139
		// Rev 2+ requires PHP 7.0.0
140
		$outscript .= "if (version_compare(PHP_VERSION, '7.0.0') < 0) {\n";
141
		$outscript .= "\terr('You need PHP Version 7.0 to update to this version');\n";
142
		$outscript .= "}\n";
143
	}
144
	$outscript .= "\n";
797 daniel-mar 145
	//$outscript .= "info('Update to OIDplus version svn-$i running...');\n";
146
	//$outscript .= "\n";
718 daniel-mar 147
	getDirContents($outdir_old, $outdir_new);
148
	$outscript .= "\n";
149
	if ($i >= 661) {
150
		$outscript .= "file_put_contents('.version.php', \"<?php // Revision $i\\n\");\n";
151
		$outscript .= "if (trim(@file_get_contents('.version.php')) !== '<?php // Revision $i') err('Could not write to .version.php!');\n";
152
		if ($i == 661) {
153
			$outscript .= "@unlink('oidplus_version.txt');\n";
154
			$outscript .= "if (is_file('oidplus_version.txt')) err('Could not delete oidplus_version.txt! Please delete it manually');\n";
155
		}
156
	} else {
157
		$outscript .= "file_put_contents('oidplus_version.txt', \"Revision $i\\n\");\n";
158
		$outscript .= "if (trim(@file_get_contents('oidplus_version.txt')) !== 'Revision $i') err('Could not write to oidplus_version.txt!');\n";
159
	}
160
	$outscript .= "\n";
161
	$outscript .= "\n";
162
	$outscript .= "info('Update to OIDplus version svn-$i done!');\n";
163
	$outscript .= "\n";
164
	$outscript .= "unlink(__FILE__);\n";
165
	$outscript .= "\n";
166
 
167
	// Now add digital signature
168
 
169
	if (strpos($outscript, '<?php') === false) {
170
		echo "Not a PHP file\n"; // Should not happen
171
		continue;
172
	}
173
 
174
	$naked = preg_replace('@<\?php /\* <ViaThinkSoftSignature>(.+)</ViaThinkSoftSignature> \*/ \?>\n@ismU', '', $outscript);
175
 
176
	$hash = hash("sha256", $naked.basename($outfile));
177
 
178
	$pkeyid = openssl_pkey_get_private('file://'.$priv_key);
179
	openssl_sign($hash, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
180
	openssl_free_key($pkeyid);
181
 
182
	if (!$signature) {
183
		echo "ERROR: Signature failed\n";
184
		continue;
185
	}
186
 
187
	$sign_line = '<?php /* <ViaThinkSoftSignature>'."\n".split_equal_length(base64_encode($signature),65).'</ViaThinkSoftSignature> */ ?>';
188
 
189
	// We have to put the signature at the beginning, because we don't know if the end of the file lacks a PHP closing tag
190
	if (substr($outscript,0,2) === '#!') {
191
		// Preserve shebang
192
		$shebang_pos = strpos($naked, "\n");
193
		$shebang = substr($naked, 0, $shebang_pos);
194
		$rest = substr($naked, $shebang_pos+1);
195
		$outscript = $shebang."\n".$sign_line."\n".$rest;
196
	} else {
197
		$outscript = $sign_line."\n".$naked;
198
	}
199
 
200
	// Write the file
201
 
202
	file_put_contents($outfile, $outscript);
203
 
204
	$ec = -1;
205
	$out = array();
206
	exec('php -l '.escapeshellarg($outfile), $out, $ec);
207
	if ($ec != 0) {
208
		fwrite(STDERR, "STOP! $outfile PHP syntax error!\n");
209
		unlink($outfile);
210
		break;
211
	}
212
	file_put_contents($outfile.'.gz', gzencode($outscript));
213
 
214
	// Delete temp dirs
215
 
216
	$ec = -1;
217
	$out = array();
218
	if ($outdir_old && is_dir($outdir_old)) exec("rm -rf $outdir_old", $out, $ec);
219
	if ($outdir_new && is_dir($outdir_new)) exec("rm -rf $outdir_new", $out, $ec);
220
}
221
echo "\n";
222
 
223
 
224
// Now write the release messages (required by software update and vnag)
225
 
226
$ec = -1;
227
$out = array();
228
exec('svn log https://svn.viathinksoft.com/svn/oidplus/trunk --xml', $out, $ec);
229
if ($ec != 0) {
230
	fwrite(STDERR, "SVN Log failed\n");
231
} else {
232
	$str = implode("\n",$out);
233
 
234
	$xml = simplexml_load_string($str);
235
 
236
	$out = array();
237
 
238
	foreach ($xml as $a) {
239
 
240
		$out[(int)$a->attributes()->revision] = array(
241
 
242
			'date' => date('Y-m-d H:i:s',strtotime((string)$a->date)),
243
			'author' => (string)$a->author,
244
			'msg' => trim((string)$a->msg),
245
 
246
		);
247
 
248
	}
249
 
250
	ksort($out);
251
 
252
	// TODO: We should also digitally sign these files?
253
	file_put_contents($output_dir.'/releases.ser', serialize($out));
254
	file_put_contents($output_dir.'/releases.ser.gz', gzencode(serialize($out)));
255
}
256
 
257
# ------------------------------------------------------------------------------------------
258
 
1130 daniel-mar 259
/**
260
 * @param string $dir_old
261
 * @param string $dir_new
262
 * @param string|null $basepath_old
263
 * @param string|null $basepath_new
264
 * @return void
265
 */
266
function getDirContents_del(string $dir_old, string $dir_new, string $basepath_old=null, string $basepath_new=null) {
647 daniel-mar 267
	global $outscript;
268
 
269
	if (is_null($basepath_old)) $basepath_old = $dir_old;
718 daniel-mar 270
	$basepath_old = my_realpath($basepath_old) . DIRECTORY_SEPARATOR;
663 daniel-mar 271
	if ($basepath_old == '/') {
272
		fwrite(STDERR, 'ARG');
273
		die();
274
	}
647 daniel-mar 275
 
718 daniel-mar 276
	$dir_old = my_realpath($dir_old) . DIRECTORY_SEPARATOR;
277
	$dir_new = my_realpath($dir_new) . DIRECTORY_SEPARATOR;
278
	$files_old = my_scandir($dir_old);
279
	//$files_new = my_scandir($dir_new);
647 daniel-mar 280
 
281
	foreach ($files_old as $file_old) {
282
		if ($file_old === '.') continue;
283
		if ($file_old === '..') continue;
284
		if ($file_old === '.svn') continue;
285
		if ($file_old === '.git') continue;
286
 
718 daniel-mar 287
		$path_old = my_realpath($dir_old . DIRECTORY_SEPARATOR . $file_old);
288
		$path_new = my_realpath($dir_new . DIRECTORY_SEPARATOR . $file_old);
647 daniel-mar 289
 
290
		$xpath_old = substr($path_old, strlen($basepath_old));
291
 
292
		if (is_dir($path_old)) {
293
			getDirContents_del($path_old, $path_new, $basepath_old, $basepath_new);
294
		}
295
 
663 daniel-mar 296
		// Note: We don't warn if a file-to-be-deleted has vanished. It would not be necessary to warn about it
647 daniel-mar 297
		if (is_dir($path_old) && !is_dir($path_new)) {
298
			$outscript .= "// Dir deleted: $xpath_old\n";
299
			$outscript .= "@rmdir('$xpath_old');\n";
663 daniel-mar 300
			$outscript .= "if (is_dir('$xpath_old')) {\n";
301
			$outscript .= "\twarn('Directory could not be deleted (was not empty?): $xpath_old');\n";
302
			$outscript .= "}\n";
303
			$outscript .= "\n";
718 daniel-mar 304
		} else if (is_file($path_old) && !is_file($path_new)) {
647 daniel-mar 305
			$outscript .= "// File deleted: $xpath_old\n";
306
			$outscript .= "@unlink('$xpath_old');\n";
718 daniel-mar 307
			$outscript .= "if (is_file('$xpath_old')) {\n";
663 daniel-mar 308
			$outscript .= "\twarn('File could not be deleted: $xpath_old');\n";
309
			$outscript .= "}\n";
310
			$outscript .= "\n";
647 daniel-mar 311
		}
312
	}
313
}
314
 
1130 daniel-mar 315
/**
316
 * @param string $dir_old
317
 * @param string $dir_new
318
 * @param string|null $basepath_old
319
 * @param string|null $basepath_new
320
 * @return void
321
 * @throws Exception
322
 */
323
function getDirContents_diff(string $dir_old, string $dir_new, string $basepath_old=null, string $basepath_new=null) {
647 daniel-mar 324
	global $outscript;
325
 
326
	if (is_null($basepath_old)) $basepath_old = $dir_old;
718 daniel-mar 327
	$basepath_old = my_realpath($basepath_old) . DIRECTORY_SEPARATOR;
663 daniel-mar 328
	if ($basepath_old == '/') {
329
		fwrite(STDERR, 'ARG');
330
		die();
331
	}
647 daniel-mar 332
 
718 daniel-mar 333
	$dir_old = my_realpath($dir_old) . DIRECTORY_SEPARATOR;
334
	$dir_new = my_realpath($dir_new) . DIRECTORY_SEPARATOR;
335
	$files_old = my_scandir($dir_old);
336
	$files_new = my_scandir($dir_new);
647 daniel-mar 337
 
338
	foreach ($files_old as $file_old) {
339
		if ($file_old === '.') continue;
340
		if ($file_old === '..') continue;
341
		if ($file_old === '.svn') continue;
342
		if ($file_old === '.git') continue;
343
 
718 daniel-mar 344
		$path_old = my_realpath($dir_old . DIRECTORY_SEPARATOR . $file_old);
345
		$path_new = my_realpath($dir_new . DIRECTORY_SEPARATOR . $file_old);
647 daniel-mar 346
 
347
		$xpath_old = substr($path_old, strlen($basepath_old));
348
 
718 daniel-mar 349
		if (is_file($path_old) && is_file($path_new)) {
647 daniel-mar 350
			if (file_get_contents($path_old) != file_get_contents($path_new)) {
351
				$outscript .= "// Files different: $xpath_old\n";
663 daniel-mar 352
 
353
				global $func_idx;
354
				$func_idx++;
355
				$outscript .= "function writefile_".$func_idx."() {\n";
356
				special_save_file($xpath_old, $path_new, $outscript, "\t@");
357
				$outscript .= "\t@touch('$xpath_old',".filemtime($path_new).");\n";
358
				$outscript .= "}\n";
359
 
718 daniel-mar 360
				$outscript .= "if (!is_file('$xpath_old')) {\n";
663 daniel-mar 361
				$outscript .= "\twarn('File has vanished! Will re-create it: $xpath_old');\n";
362
				$outscript .= "\twritefile_".$func_idx."();\n";
718 daniel-mar 363
				$outscript .= "\tif (!is_file('$xpath_old')) {\n";
663 daniel-mar 364
				$outscript .= "\t\twarn('File cannot be created (not existing): $xpath_old');\n";
365
				$outscript .= "\t} else if (sha1_file('$xpath_old') != '".sha1_file($path_new)."') {\n";
366
				$outscript .= "\t\twarn('File cannot be created (checksum mismatch): $xpath_old');\n";
367
				$outscript .= "\t} else if ((DIRECTORY_SEPARATOR === '/') && !@chmod('$xpath_old', 0".sprintf('%o', fileperms($path_new) & 0777).")) {\n";
368
				$outscript .= "\t\twarn('Could not change file permissions of ".$xpath_old."');\n";
369
				$outscript .= "\t}\n";
370
 
371
				$outscript .= "} else {\n";
372
 
686 daniel-mar 373
				$outscript .= "\tif (@sha1_file('$xpath_old') !== '".sha1_file($path_new)."') {\n"; // it is possible that the file is already updated (e.g. by a manual hotfix)
374
				$outscript .= "\t\tif (@sha1_file('$xpath_old') !== '".sha1_file($path_old)."') {\n";
375
				$outscript .= "\t\t\twarn('File was modified. Will overwrite the changes now: $xpath_old');\n";
376
				$outscript .= "\t\t\t\$tmp = pathinfo('$xpath_old');\n";
377
				$outscript .= "\t\t\t\$backup_name = \$tmp['dirname'].DIRECTORY_SEPARATOR.\$tmp['filename'].'.'.date('Ymdhis',@filemtime('$xpath_old')).(isset(\$tmp['extension']) ? '.'.\$tmp['extension'] : '');\n";
378
				$outscript .= "\t\t\twarn('Creating a backup as '.\$backup_name);\n";
379
				$outscript .= "\t\t\tif (!@copy('$xpath_old', \$backup_name)) {\n";
380
				$outscript .= "\t\t\t\twarn('Creation of backup failed');\n";
381
				$outscript .= "\t\t\t}\n";
663 daniel-mar 382
				$outscript .= "\t\t}\n";
686 daniel-mar 383
				$outscript .= "\t\twritefile_".$func_idx."();\n";
384
				$outscript .= "\t\tif (@sha1_file('$xpath_old') !== '".sha1_file($path_new)."') {\n";
385
				$outscript .= "\t\t\twarn('File cannot be written (checksum mismatch): $xpath_old');\n";
386
				$outscript .= "\t\t}\n";
663 daniel-mar 387
				$outscript .= "\t}\n";
686 daniel-mar 388
 
663 daniel-mar 389
				$outscript .= "}\n";
390
				$outscript .= "\n";
647 daniel-mar 391
			}
392
			if ((fileperms($path_old) & 0777) != (fileperms($path_new) & 0777)) {
393
				$outscript .= "// Different file chmod: $xpath_old\n";
663 daniel-mar 394
				$outscript .= "if ((DIRECTORY_SEPARATOR === '/') && !@chmod('$xpath_old', 0".sprintf('%o', fileperms($path_new) & 0777).")) {\n";
395
				$outscript .= "\twarn('Could not change file permissions of ".$xpath_old."');\n";
396
				$outscript .= "}\n";
397
				$outscript .= "\n";
647 daniel-mar 398
			}
399
		} else if (is_dir($path_old) && is_dir($path_new)) {
718 daniel-mar 400
			/*
663 daniel-mar 401
			$outscript .= "// Verify that directory exists: $xpath_old\n";
402
			$outscript .= "if (!is_dir('$xpath_old')) {\n";
403
			$outscript .= "\twarn('Directory has vanished! Will re-create it: $xpath_old');\n";
404
			$outscript .= "\t@mkdir('$xpath_old');\n";
405
			$outscript .= "\tif (!is_dir('$xpath_old')) {\n";
406
			$outscript .= "\t\twarn('Directory could not be created: $xpath_old');\n";
407
			$outscript .= "\t}\n";
408
			$outscript .= "}\n";
409
			$outscript .= "\n";
718 daniel-mar 410
			*/
663 daniel-mar 411
 
647 daniel-mar 412
			if ((fileperms($path_old) & 0777) != (fileperms($path_new) & 0777)) {
413
				$outscript .= "// Different dir chmod: $xpath_old\n";
663 daniel-mar 414
				$outscript .= "if ((DIRECTORY_SEPARATOR === '/') && !@chmod('$xpath_old', 0".sprintf('%o', fileperms($path_new) & 0777).")) {\n";
415
				$outscript .= "\twarn('Could not change dir permissions of ".$xpath_old."');\n";
416
				$outscript .= "}\n";
417
				$outscript .= "\n";
647 daniel-mar 418
			}
419
		}
420
 
421
		if (is_dir($path_old)) {
422
			getDirContents_diff($path_old, $path_new, $basepath_old, $basepath_new);
423
		}
424
	}
425
}
426
 
1130 daniel-mar 427
/**
428
 * @param string $dir_old
429
 * @param string $dir_new
430
 * @param string|null $basepath_old
431
 * @param string|null $basepath_new
432
 * @return void
433
 * @throws Exception
434
 */
435
function getDirContents_add(string $dir_old, string $dir_new, string $basepath_old=null, string $basepath_new=null) {
647 daniel-mar 436
	global $outscript;
437
 
438
	if (is_null($basepath_new)) $basepath_new = $dir_new;
718 daniel-mar 439
	$basepath_new = my_realpath($basepath_new) . DIRECTORY_SEPARATOR;
663 daniel-mar 440
	if ($basepath_new == '/') {
441
		fwrite(STDERR, 'ARG');
442
		die();
443
	}
647 daniel-mar 444
 
718 daniel-mar 445
	$dir_old = my_realpath($dir_old) . DIRECTORY_SEPARATOR;
446
	$dir_new = my_realpath($dir_new) . DIRECTORY_SEPARATOR;
447
	//$files_old = my_scandir($dir_old);
448
	$files_new = my_scandir($dir_new);
647 daniel-mar 449
 
450
	foreach ($files_new as $file_new) {
451
		if ($file_new === '.') continue;
452
		if ($file_new === '..') continue;
453
		if ($file_new === '.svn') continue;
454
		if ($file_new === '.git') continue;
455
 
718 daniel-mar 456
		$path_old = my_realpath($dir_old . DIRECTORY_SEPARATOR . $file_new);
457
		$path_new = my_realpath($dir_new . DIRECTORY_SEPARATOR . $file_new);
647 daniel-mar 458
 
459
		$xpath_new = substr($path_new, strlen($basepath_new));
460
 
461
		if (is_dir($path_new) && !is_dir($path_old)) {
663 daniel-mar 462
			// Note: We are not warning if the dir was already created by the user
647 daniel-mar 463
			$outscript .= "// Dir added: $xpath_new\n";
464
			$outscript .= "@mkdir('$xpath_new');\n";
663 daniel-mar 465
			$outscript .= "if (!is_dir('$xpath_new')) {\n";
466
			$outscript .= "\twarn('Directory could not be created: $xpath_new');\n";
467
			$outscript .= "} else if ((DIRECTORY_SEPARATOR === '/') && !@chmod('$xpath_new', 0".sprintf('%o', fileperms($path_new) & 0777).")) {\n";
468
			$outscript .= "\twarn('Could not change directory permissions of ".$xpath_new."');\n";
469
			$outscript .= "}\n";
470
			$outscript .= "\n";
797 daniel-mar 471
 
718 daniel-mar 472
			// we create it locally, so that the recursive code still works
473
			mkdir($dir_old . DIRECTORY_SEPARATOR . $file_new);
474
			$path_old = my_realpath($dir_old . DIRECTORY_SEPARATOR . $file_new);
797 daniel-mar 475
 
718 daniel-mar 476
		} else if (is_file($path_new) && !is_file($path_old)) {
647 daniel-mar 477
			$outscript .= "// File added: $xpath_new\n";
663 daniel-mar 478
 
479
			global $func_idx;
480
			$func_idx++;
481
			$outscript .= "function writefile_".$func_idx."() {\n";
482
			special_save_file($xpath_new, $path_new, $outscript, "\t@");
483
			$outscript .= "\t@touch('$xpath_new',".filemtime($path_new).");\n";
484
			$outscript .= "}\n";
485
 
486
			// Note: We will not warn if the file was created and is exactly the file we want
718 daniel-mar 487
			$outscript .= "if (is_file('$xpath_new') && (sha1_file('$xpath_new') != '".sha1_file($path_new)."')) {\n";
663 daniel-mar 488
			$outscript .= "\twarn('File was created by someone else. Will overwrite the changes now: $xpath_new');\n";
664 daniel-mar 489
			$outscript .= "\t\$tmp = pathinfo('$xpath_new');\n";
667 daniel-mar 490
			$outscript .= "\t\$backup_name = \$tmp['dirname'].DIRECTORY_SEPARATOR.\$tmp['filename'].'.'.date('Ymdhis',@filemtime('$xpath_new')).(isset(\$tmp['extension']) ? '.'.\$tmp['extension'] : '');\n";
663 daniel-mar 491
			$outscript .= "\twarn('Creating a backup as '.\$backup_name);\n";
492
			$outscript .= "\tif (!@copy('$xpath_new', \$backup_name)) {\n";
493
			$outscript .= "\t\twarn('Creation of backup failed');\n";
494
			$outscript .= "\t}\n";
495
			$outscript .= "}\n";
496
 
497
			$outscript .= "writefile_".$func_idx."();\n";
718 daniel-mar 498
			$outscript .= "if (!is_file('$xpath_new')) {\n";
663 daniel-mar 499
			$outscript .= "\twarn('File cannot be created (not existing): $xpath_new');\n";
500
			$outscript .= "} else if (sha1_file('$xpath_new') != '".sha1_file($path_new)."') {\n";
501
			$outscript .= "\twarn('File cannot be created (checksum mismatch): $xpath_new');\n";
502
			$outscript .= "} else if ((DIRECTORY_SEPARATOR === '/') && !@chmod('$xpath_new', 0".sprintf('%o', fileperms($path_new) & 0777).")) {\n";
503
			$outscript .= "\twarn('Could not change file permissions of ".$xpath_new."');\n";
504
			$outscript .= "}\n";
505
			$outscript .= "\n";
647 daniel-mar 506
		}
507
 
508
		if (is_dir($path_new)) {
509
			getDirContents_add($path_old, $path_new, $basepath_old, $basepath_new);
510
		}
511
	}
512
}
513
 
1130 daniel-mar 514
/**
515
 * @param string $dir_old
516
 * @param string $dir_new
517
 * @return void
518
 * @throws Exception
519
 */
520
function getDirContents(string $dir_old, string $dir_new) {
663 daniel-mar 521
	global $func_idx;
522
	$func_idx = 0;
647 daniel-mar 523
	getDirContents_add($dir_old, $dir_new);
524
	getDirContents_diff($dir_old, $dir_new);
652 daniel-mar 525
	getDirContents_del($dir_old, $dir_new);
647 daniel-mar 526
}
527
 
1130 daniel-mar 528
/**
529
 * @param int $rev
530
 * @param string $dir
531
 * @return void
532
 */
533
function hotfix_dir(int $rev, string $dir) {
718 daniel-mar 534
	if ($rev == 699) {
535
		// Fix syntax error that lead to a stalled update!
536
		$file = $dir.'/plugins/viathinksoft/adminPages/900_software_update/OIDplusPageAdminSoftwareUpdate.class.php';
537
		$cont = file_get_contents($file);
831 daniel-mar 538
		$cont = str_replace("urlencode('oidplus:system_file_check',OIDplus::getEditionInfo()['downloadpage']))",
539
		                    "urlencode('oidplus:system_file_check'),OIDplus::getEditionInfo()['downloadpage'])",
540
		                    $cont);
718 daniel-mar 541
		file_put_contents($file, $cont);
647 daniel-mar 542
 
718 daniel-mar 543
		// Fix syntax error that lead to a stalled update!
544
		$file = $dir.'/plugins/viathinksoft/adminPages/901_vnag_version_check/vnag.php';
545
		$cont = file_get_contents($file);
546
		$cont = str_replace("\t\tOIDplus::getEditionInfo()", "", $cont);
547
		file_put_contents($file, $cont);
661 daniel-mar 548
	}
831 daniel-mar 549
	if ($rev == 830) {
832 daniel-mar 550
		// Fix bug that caused system ID to get lost
831 daniel-mar 551
		$file = $dir.'/includes/classes/OIDplus.class.php';
552
		$cont = file_get_contents($file);
553
		$cont = str_replace("if ((\$passphrase === false) || !is_privatekey_encrypted(\$privKey)) {",
554
		                    "if ((\$passphrase === false) || !is_privatekey_encrypted(OIDplus::config()->getValue('oidplus_private_key'))) {",
555
		                    $cont);
556
		file_put_contents($file, $cont);
557
	}
857 daniel-mar 558
	if ($rev == 856) {
559
		// Fix runtime error that lead to a stalled update!
560
		$file = $dir.'/includes/classes/OIDplus.class.php';
561
		$cont = file_get_contents($file);
562
		$cont = str_replace('$this->recanonizeObjects();', '', $cont);
563
		file_put_contents($file, $cont);
564
	}
1109 daniel-mar 565
	if ($rev == 1108) {
566
		// Fix runtime error that lead to a stalled update!
567
		$file = $dir.'/vendor/danielmarschall/php_utils/vts_crypt.inc.php';
568
		$cont = file_get_contents($file);
569
		$cont = str_replace('echo "OK, password $password\n";', '', $cont);
570
		file_put_contents($file, $cont);
571
	}
647 daniel-mar 572
}
648 daniel-mar 573
 
1130 daniel-mar 574
/**
575
 * @param string $data
576
 * @param int $width
577
 * @return string
578
 */
579
function split_equal_length(string $data, int $width=65): string {
663 daniel-mar 580
	$res = '';
651 daniel-mar 581
	for ($i=0; $i<strlen($data); $i+=$width) {
663 daniel-mar 582
		$res .= substr($data, $i, $width)."\n";
651 daniel-mar 583
	}
663 daniel-mar 584
	return $res;
661 daniel-mar 585
}
663 daniel-mar 586
 
1130 daniel-mar 587
/**
588
 * @param string $out_file
589
 * @param string $in_file
590
 * @param string $res
591
 * @param string $line_prefix
592
 * @param int $width
593
 * @return void
594
 * @throws Exception
595
 */
596
function special_save_file(string $out_file, string $in_file, string &$res, string $line_prefix, int $width=50) {
663 daniel-mar 597
	$handle = @fopen($in_file, "rb");
598
	if (!$handle) {
599
		throw new Exception("Cannot open file $in_file");
600
	}
797 daniel-mar 601
	$res .= $line_prefix."\$fp = fopen('$out_file', 'w');\n";
602
 
663 daniel-mar 603
	while (!feof($handle)) {
604
		// important: must be a multiple of 3, otherwise we have base64 paddings!
605
		$buffer = fread($handle, $width*3);
606
		$base64 = base64_encode($buffer);
797 daniel-mar 607
		$res .= $line_prefix."fwrite(\$fp, base64_decode('".$base64."'));\n";
663 daniel-mar 608
	}
797 daniel-mar 609
 
610
	$res .= $line_prefix."fclose(\$fp);\n";
663 daniel-mar 611
	fclose($handle);
612
}
718 daniel-mar 613
 
1130 daniel-mar 614
/**
615
 * @param string $name
616
 * @return mixed|string
617
 */
618
function my_realpath(string $name) {
718 daniel-mar 619
	$ret = realpath($name);
620
	return ($ret === false) ? $name : $ret;
621
}
622
 
1130 daniel-mar 623
/**
624
 * @param string $dir
625
 * @return array
626
 */
627
function my_scandir(string $dir): array {
718 daniel-mar 628
	$ret = @scandir($dir);
629
	if ($ret === false) return array();
630
	return $ret;
631
}