Subversion Repositories SvarDOS

Rev

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

Rev Author Line No. Line
562 mateuszvis 1
<?php /*
2
 
3
  SvarDOS repo index builder
4
  Copyright (C) Mateusz Viste 2012-2022
5
 
734 bttr 6
  buildidx computes an index json file for the SvarDOS repository.
673 mateusz.vi 7
  it must be executed pointing to a directory that stores packages (*.svp)
562 mateuszvis 8
  files. buildidx will generate the index file and save it into the package
9
  repository.
10
 
11
  requires php-zip
12
 
951 mateusz.vi 13
  24 feb 2022: added hardcoded hack to translate version 'x.xx' to '0.44' (NESticle)
941 mateusz.vi 14
  23 feb 2022: basic validation of source archives (not empty + matches an existing svp file)
912 mateusz.vi 15
  21 feb 2022: buildidx collects categories looking at the dir layout of each package + improved version string parsing (replaced version_compare call by dos_version_compare)
775 mateusz.vi 16
  17 feb 2022: checking for non-8+3 filenames in packages and duplicates + devload no longer part of CORE
736 mateusz.vi 17
  16 feb 2022: added warning about overlong version strings and wild files location
719 mateusz.vi 18
  15 feb 2022: index is generated as json, contains all filenames and alt versions
673 mateusz.vi 19
  14 feb 2022: packages are expected to have the *.svp extension
650 mateusz.vi 20
  12 feb 2022: skip source packages from being processed (*.src.zip)
562 mateuszvis 21
  20 jan 2022: rewritten the code from ANSI C to PHP for easier maintenance
22
  13 feb 2021: 'title' LSM field is no longer looked after
23
  11 feb 2021: lsm headers are no longer checked, so it is compatible with the simpler lsm format used by SvarDOS
24
  13 jan 2021: removed the identification line, changed CRC32 to bsum, not creating the listing.txt file and stopped compressing index
25
  23 apr 2017: uncompressed index is no longer created, added CRC32 of zib (bin only) files, if present
26
  28 aug 2016: listing.txt is always written inside the repo dir (instead of inside current dir)
27
  27 aug 2016: accepting full paths to repos (starting with /...)
28
  07 dec 2013: rewritten buildidx in ANSI C89
29
  19 aug 2013: add a compressed version of the index file to repos (index.gz)
30
  22 jul 2013: creating a listing.txt file with list of packages
31
  18 jul 2013: writing the number of packaged into the first line of the lst file
32
  11 jul 2013: added a switch to 7za to make it case insensitive when extracting lsm files
33
  10 jul 2013: changed unzip calls to 7za (to handle cases when appinfo is compressed with lzma)
34
  04 feb 2013: added CRC32 support
35
  22 sep 2012: forked 1st version from FDUPDATE builder
36
*/
37
 
951 mateusz.vi 38
$PVER = "20220224";
562 mateuszvis 39
 
40
 
41
// computes the BSD sum of a file and returns it
42
function file2bsum($fname) {
43
  $result = 0;
44
 
45
  $fd = fopen($fname, 'rb');
46
  if ($fd === false) return(0);
47
 
48
  while (!feof($fd)) {
49
 
50
    $buff = fread($fd, 1024 * 1024);
51
 
563 mateuszvis 52
    $slen = strlen($buff);
53
    for ($i = 0; $i < $slen; $i++) {
562 mateuszvis 54
      // rotr
55
      $result = ($result >> 1) | ($result << 15);
56
      // add and truncate to 16 bits
563 mateuszvis 57
      $result += ord($buff[$i]);
562 mateuszvis 58
      $result &= 0xffff;
59
    }
60
  }
61
 
62
  fclose($fd);
63
  return($result);
64
}
65
 
66
 
912 mateusz.vi 67
// translates a version string into a array of integer values.
68
// Accepted formats follow:
69
//    300.12.1
70
//    1
71
//    12.2.34.2-4.5
72
//    1.2c
73
//    1.01 beta+3
74
//    2013-12-31
75
//    20220222 alpha
76
function vertoarr($verstr) {
77
  $subver = array(0,0,0,0);
78
 
79
  // switch string to lcase for easier processing and trim any leading or trailing white spaces
80
  $verstr = strtolower(trim($verstr));
81
 
82
  // replace all '-' and '/' characters to '.' (uniformization of sub-version parts delimiters)
83
  $verstr = strtr($verstr, '-/', '..');
84
 
85
  // is there a subversion value? (for example "+4" in "1.05+4")
86
  $i = strrpos($verstr, '+', 1);
87
  if ($i !== false) {
88
    // validate the svar-version is a proper integer
89
    $svarver = substr($verstr, $i + 1);
90
    if (! preg_match('/[1-9][0-9]*/', $svarver)) {
91
      return(false);
92
    }
93
    $subver[3] = intval($svarver); // set the +rev as a very minor item
94
    $verstr = substr($verstr, 0, $i);
95
  }
96
 
951 mateusz.vi 97
  // NESticls hack: version "x.xx" is translated to "0.44"... that sucks but that's how it is.
98
  // ref: https://web.archive.org/web/20070205074631/http://www.zophar.net/NESticle/
99
  if ($verstr == 'x.xx') $verstr = '0.44';
100
 
936 mateusz.vi 101
  // beta reordering: convert "beta 0.95" to "0.95 beta"
102
  if (preg_match('/^beta /', $verstr)) $verstr = substr($verstr, 5) . ' beta';
103
 
927 mateusz.vi 104
  // any occurence of alpha,beta,gamma,delta etc preceded by a digit should have a space separator added
105
  // example: "2.6.0pre9" becomes "2.6.0 pre9"
106
  $verstr = preg_replace('/([0-9])(alpha|beta|gamma|delta|pre|rc|patch)/', '$1 $2', $verstr);
107
 
108
  // same as above, but this time adding a trailing space separator
109
  // example: "2.6.0 pre9" becomes "2.6.0 pre 9"
110
  $verstr = preg_replace('/(alpha|beta|gamma|delta|pre|rc|patch)([0-9])/', '$1 $2', $verstr);
111
 
921 mateusz.vi 112
  // is the version ending with ' alpha', 'beta', etc?
922 mateusz.vi 113
  if (preg_match('/ (alpha|beta|gamma|delta|pre|rc|patch)( [0-9]{1,4}){0,1}$/', $verstr)) {
921 mateusz.vi 114
    // if there is a trailing beta-number, process it first
115
    if (preg_match('/ [0-9]{1,4}$/', $verstr)) {
116
      $i = strrpos($verstr, ' ');
117
      $subver[2] = intval(substr($verstr, $i + 1));
118
      $verstr = trim(substr($verstr, 0, $i));
119
    }
912 mateusz.vi 120
    $i = strrpos($verstr, ' ');
121
    $greek = substr($verstr, $i + 1);
122
    $verstr = trim(substr($verstr, 0, $i));
123
    if ($greek == 'alpha') {
921 mateusz.vi 124
      $subver[1] = 1;
912 mateusz.vi 125
    } else if ($greek == 'beta') {
921 mateusz.vi 126
      $subver[1] = 2;
920 mateusz.vi 127
    } else if ($greek == 'gamma') {
921 mateusz.vi 128
      $subver[1] = 3;
920 mateusz.vi 129
    } else if ($greek == 'delta') {
921 mateusz.vi 130
      $subver[1] = 4;
131
    } else if ($greek == 'pre') {
132
      $subver[1] = 5;
914 mateusz.vi 133
    } else if ($greek == 'rc') {
921 mateusz.vi 134
      $subver[1] = 6;
922 mateusz.vi 135
    } else if ($greek == 'patch') { // this is a POST-release version, as opposed to all above that are PRE-release versions
136
      $subver[1] = 99;
912 mateusz.vi 137
    } else {
138
      return(false);
139
    }
914 mateusz.vi 140
  } else {
922 mateusz.vi 141
    $subver[1] = 98; // one less than the 'patch' level
912 mateusz.vi 142
  }
143
 
144
  // does the version string have a single-letter subversion? (1.0c)
145
  if (preg_match('/[a-z]$/', $verstr)) {
921 mateusz.vi 146
    $subver[0] = ord(substr($verstr, -1));
912 mateusz.vi 147
    $verstr = substr_replace($verstr, '', -1); // remove last character from string
148
  }
149
 
926 mateusz.vi 150
  // convert "30-jan-99", "1999-jan-30" and "30-jan-1999" versions to "30jan99" or "30jan1999"
151
  // note that dashes have already been replaced by dots
152
  if (preg_match('/^([0-9][0-9]){1,2}\.(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\.([0-9][0-9]){1,2}$/', $verstr)) {
153
    $verstr = str_replace('.', '', $verstr);
154
  }
155
 
156
  // convert "2009mar17" versions to "17mar2009"
157
  if (preg_match('/^[0-9]{4}(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[0-9]{2}$/', $verstr)) {
158
    $dy = substr($verstr, 7);
159
    $mo = substr($verstr, 4, 3);
160
    $ye = substr($verstr, 0, 4);
925 mateusz.vi 161
    $verstr = "{$dy}{$mo}{$ye}";
923 mateusz.vi 162
  }
163
 
164
  // convert "30jan99" versions to 99.1.30 and "30jan1999" to 1999.1.30
925 mateusz.vi 165
  if (preg_match('/^[0-3][0-9](jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)([0-9][0-9]){1,2}$/', $verstr)) {
923 mateusz.vi 166
    $months = array('jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8, 'sep' => 9, 'oct' => 10, 'nov' => 11, 'dec' => 12);
167
    $dy = substr($verstr, 0, 2);
168
    $mo = $months[substr($verstr, 2, 3)];
169
    $ye = substr($verstr, 5);
170
    $verstr = "{$ye}.{$mo}.{$dy}";
171
  }
172
 
912 mateusz.vi 173
  // validate the format is supported, should be something no more complex than 1.05.3.33
919 mateusz.vi 174
  if (! preg_match('/^[0-9][0-9.]{0,20}$/', $verstr)) {
912 mateusz.vi 175
    return(false);
176
  }
177
 
178
  // NOTE: a zero right after a separator and trailed with a digit (as in 1.01)
179
  //       has a special meaning
180
  $exploded = explode('.', $verstr);
181
  if (count($exploded) > 16) {
182
    return(false);
183
  }
921 mateusz.vi 184
  $exploded[16] = $subver[0]; // a-z (1.0c)
185
  $exploded[17] = $subver[1]; // alpha/beta/gamma/delta/rc/pre
186
  $exploded[18] = $subver[2]; // alpha-beta-gamma subversion (eg. "beta 9")
912 mateusz.vi 187
  $exploded[19] = $subver[3]; // svar-ver (1.0+5)
188
  for ($i = 0; $i < 20; $i++) if (empty($exploded[$i])) $exploded[$i] = '0';
189
 
190
  ksort($exploded);
191
 
192
  return($exploded);
193
}
194
 
195
 
196
function dos_version_compare($v1, $v2) {
197
  $v1arr = vertoarr($v1);
198
  $v2arr = vertoarr($v2);
199
  for ($i = 0; $i < count($v1arr); $i++) {
921 mateusz.vi 200
    if ($v1arr[$i] > $v2arr[$i]) return(1);
201
    if ($v1arr[$i] < $v2arr[$i]) return(-1);
912 mateusz.vi 202
  }
203
  return(0);
204
}
205
 
206
 
562 mateuszvis 207
// reads file fil from zip archive z and returns its content, or false on error
208
function read_file_from_zip($z, $fil) {
209
  $zip = new ZipArchive;
210
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
211
    echo "ERROR: failed to open zip file '{$z}'\n";
212
    return(false);
213
  }
214
 
215
  // load the appinfo/pkgname.lsm file
216
  $res = $zip->getFromName($fil, 8192, ZipArchive::FL_NOCASE);
217
 
218
  $zip->close();
219
  return($res);
220
}
221
 
222
 
731 mateusz.vi 223
function read_list_of_files_in_zip($z) {
224
  $zip = new ZipArchive;
225
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
226
    echo "ERROR: failed to open zip file '{$z}'\n";
227
    return(false);
228
  }
229
 
230
  $res = array();
231
  for ($i = 0; $i < $zip->numFiles; $i++) $res[] = $zip->getNameIndex($i);
232
 
233
  $zip->close();
234
  return($res);
235
}
236
 
237
 
562 mateuszvis 238
// reads a LSM string and returns it in the form of an array
239
function parse_lsm($s) {
240
  $res = array();
241
  for ($l = strtok($s, "\n"); $l !== false; $l = strtok("\n")) {
242
    // the line is "token: value", let's find the colon
243
    $colpos = strpos($l, ':');
244
    if (($colpos === false) || ($colpos === 0)) continue;
245
    $tok = strtolower(trim(substr($l, 0, $colpos)));
246
    $val = trim(substr($l, $colpos + 1));
247
    $res[$tok] = $val;
248
  }
249
  return($res);
250
}
251
 
252
 
731 mateusz.vi 253
// on PHP 8+ there is str_starts_with(), but not on PHP 7 so I use this
254
function str_head_is($haystack, $needle) {
255
  return strpos($haystack, $needle) === 0;
256
}
257
 
258
 
791 mateusz.vi 259
// returns an array that contains CORE packages (populated from the core subdirectory in pkgdir)
260
function load_core_list($repodir) {
261
  $res = array();
262
 
263
  foreach (scandir($repodir . '/core/') as $f) {
264
    if (!preg_match('/\.svp$/', $f)) continue;
265
    $res[] = explode('.', $f)[0];
266
  }
267
  return($res);
268
}
269
 
270
 
562 mateuszvis 271
// ***************** MAIN ROUTINE *********************************************
272
 
719 mateusz.vi 273
//echo "SvarDOS repository index generator ver {$PVER}\n";
562 mateuszvis 274
 
275
if (($_SERVER['argc'] != 2) || ($_SERVER['argv'][1][0] == '-')) {
276
  echo "usage: php buildidx.php repodir\n";
277
  exit(1);
278
}
279
 
280
$repodir = $_SERVER['argv'][1];
281
 
282
$pkgfiles = scandir($repodir);
283
$pkgcount = 0;
284
 
738 mateusz.vi 285
 
795 mateusz.vi 286
// load the list of CORE and MSDOS_COMPAT packages
738 mateusz.vi 287
 
791 mateusz.vi 288
$core_packages_list = load_core_list($repodir);
804 bttr 289
$msdos_compat_list = explode(' ', 'append assign attrib chkdsk choice command comp cpidos debug defrag deltree diskcomp diskcopy display edit edlin exe2bin fc fdapm fdisk find format help himemx kernel keyb label localcfg mem mirror mode more move nlsfunc print replace share shsucdx sort swsubst tree undelete unformat xcopy');
738 mateusz.vi 290
 
719 mateusz.vi 291
// do a list of all svp packages with their available versions and descriptions
562 mateuszvis 292
 
719 mateusz.vi 293
$pkgdb = array();
294
foreach ($pkgfiles as $fname) {
562 mateuszvis 295
 
941 mateusz.vi 296
  // zip files (ie. source archives)
297
  if (preg_match('/\.zip$/', $fname)) {
298
    // the zip archive should contain at least one file
299
    if (count(read_list_of_files_in_zip($repodir . '/' . $fname)) < 1) echo "WARNING: source archive {$fname} contains no files (either empty or corrupted)\n";
300
    // check that the file relates to an existing svp package
301
    $svpfname = preg_replace('/zip$/', 'svp', $fname);
302
    if (!file_exists($repodir . '/' . $svpfname)) echo "ERROR: orphaned source archive '{$fname}' (no matching svp file, expecting a package named '{$svpfname}')\n";
303
    // that is for zip files
304
    continue;
305
  }
306
 
307
  // skip (and warn about) non-svp
308
  if (!preg_match('/\.svp$/', $fname)) {
946 mateusz.vi 309
    $okfiles = array('.', '..', '_cats.json', '_index.json', '_buildidx.log', 'core');
941 mateusz.vi 310
    if (array_search($fname, $okfiles) !== false) continue;
311
    echo "WARNING: wild file '{$fname} (this is either an useless file that should be removed, or a misnamed package or source archive)'\n";
312
    continue;
313
  }
314
 
801 mateusz.vi 315
  if (!preg_match('/^[a-zA-Z0-9+. _-]*\.svp$/', $fname)) {
316
    echo "ERROR: {$fname} has a very weird name\n";
317
    continue;
318
  }
319
 
719 mateusz.vi 320
  $path_parts = pathinfo($fname);
321
  $pkgnam = explode('-', $path_parts['filename'])[0];
322
  $pkgfullpath = realpath($repodir . '/' . $fname);
562 mateuszvis 323
 
719 mateusz.vi 324
  $lsm = read_file_from_zip($pkgfullpath, "appinfo/{$pkgnam}.lsm");
562 mateuszvis 325
  if ($lsm == false) {
802 mateusz.vi 326
    echo "ERROR: {$fname} does not contain an LSM file at the expected location\n";
719 mateusz.vi 327
    continue;
562 mateuszvis 328
  }
329
  $lsmarray = parse_lsm($lsm);
330
  if (empty($lsmarray['version'])) {
719 mateusz.vi 331
    echo "ERROR: lsm file in {$fname} does not contain a version\n";
332
    continue;
562 mateuszvis 333
  }
730 mateusz.vi 334
  if (strlen($lsmarray['version']) > 16) {
737 mateusz.vi 335
    echo "ERROR: version string in lsm file of {$fname} is too long (16 chars max)\n";
730 mateusz.vi 336
    continue;
337
  }
562 mateuszvis 338
  if (empty($lsmarray['description'])) {
719 mateusz.vi 339
    echo "ERROR: lsm file in {$fname} does not contain a description\n";
340
    continue;
562 mateuszvis 341
  }
342
 
731 mateusz.vi 343
  // validate the files present in the archive
344
  $listoffiles = read_list_of_files_in_zip($pkgfullpath);
739 mateusz.vi 345
  $pkgdir = $pkgnam;
346
 
768 mateusz.vi 347
  // special rule for "parent and children" packages
348
  if (str_head_is($pkgnam, 'djgpp_')) $pkgdir = 'djgpp'; // djgpp_* packages put their files in djgpp
754 mateusz.vi 349
  if ($pkgnam == 'fbc_help') $pkgdir = 'fbc'; // FreeBASIC help goes to the FreeBASIC dir
802 mateusz.vi 350
  if ($pkgnam == 'clamdb') $pkgdir = 'clamav'; // data patterns for clamav
739 mateusz.vi 351
 
768 mateusz.vi 352
  // array used to detect duplicated entries after lower-case conversion
353
  $duparr = array();
354
 
909 mateusz.vi 355
  // will hold the list of categories that this package belongs to
356
  $catlist = array();
357
 
731 mateusz.vi 358
  foreach ($listoffiles as $f) {
359
    $f = strtolower($f);
768 mateusz.vi 360
    $path_array = explode('/', $f);
361
    // emit a warning when non-8+3 filenames are spotted and find duplicates
362
    foreach ($path_array as $item) {
363
      if (empty($item)) continue; // skip empty items at end of paths (eg. appinfo/)
364
      if (!preg_match("/[a-z0-9!#$%&'()@^_`{}~-]{1,8}(\.[a-z0-9!#$%&'()@^_`{}~-]{1,3}){0,1}/", $item)) {
365
        echo "WARNING: {$fname} contains a non-8+3 path (or weird char): {$item} (in $f)\n";
366
      }
367
    }
368
    // look for dups
369
    if (array_search($f, $duparr) !== false) {
370
      echo "WARNING: {$fname} contains a duplicated entry: '{$f}'\n";
371
    } else {
372
      $duparr[] = $f;
373
    }
731 mateusz.vi 374
    // LSM file is ok
375
    if ($f === "appinfo/{$pkgnam}.lsm") continue;
376
    if ($f === "appinfo/") continue;
795 mateusz.vi 377
    // CORE and MSDOS_COMPAT packages are premium citizens and can do a little more
909 mateusz.vi 378
    $core_or_msdoscompat = 0;
379
    if (array_search($pkgnam, $core_packages_list) !== false) {
380
      $catlist[] = 'core';
381
      $core_or_msdoscompat = 1;
382
    }
383
    if (array_search($pkgnam, $msdos_compat_list) !== false) {
384
      $catlist[] = 'msdos_compat';
385
      $core_or_msdoscompat = 1;
386
    }
387
    if ($core_or_msdoscompat == 1) {
736 mateusz.vi 388
      if (str_head_is($f, 'bin/')) continue;
779 mateusz.vi 389
      if (str_head_is($f, 'cpi/')) continue;
749 mateusz.vi 390
      if (str_head_is($f, "doc/{$pkgdir}/")) continue;
391
      if ($f === 'doc/') continue;
392
      if (str_head_is($f, "nls/{$pkgdir}.")) continue;
393
      if ($f === 'nls/') continue;
736 mateusz.vi 394
    }
798 mateusz.vi 395
    // the help package is allowed to put files in... help
396
    if (($pkgnam == 'help') && (str_head_is($f, 'help/'))) continue;
909 mateusz.vi 397
    // must be category-prefixed file, add it to the list of categories for this package
398
    $catlist[] = explode('/', $f)[0];
749 mateusz.vi 399
    // well-known "category" dirs are okay
739 mateusz.vi 400
    if (str_head_is($f, "progs/{$pkgdir}/")) continue;
731 mateusz.vi 401
    if ($f === 'progs/') continue;
739 mateusz.vi 402
    if (str_head_is($f, "devel/{$pkgdir}/")) continue;
731 mateusz.vi 403
    if ($f === 'devel/') continue;
739 mateusz.vi 404
    if (str_head_is($f, "games/{$pkgdir}/")) continue;
731 mateusz.vi 405
    if ($f === 'games/') continue;
739 mateusz.vi 406
    if (str_head_is($f, "drivers/{$pkgdir}/")) continue;
731 mateusz.vi 407
    if ($f === 'drivers/') continue;
768 mateusz.vi 408
    echo "WARNING: {$fname} contains a file in an illegal location: {$f}\n";
731 mateusz.vi 409
  }
410
 
912 mateusz.vi 411
  // do I understand the version string?
412
  if (vertoarr($lsmarray['version']) === false) echo "WARNING: {$fname} parsing of version string failed ('{$lsmarray['version']}')\n";
413
 
719 mateusz.vi 414
  $meta['fname'] = $fname;
415
  $meta['desc'] = $lsmarray['description'];
909 mateusz.vi 416
  $meta['cats'] = array_unique($catlist);
719 mateusz.vi 417
 
418
  $pkgdb[$pkgnam][$lsmarray['version']] = $meta;
419
}
420
 
801 mateusz.vi 421
 
719 mateusz.vi 422
$db = array();
909 mateusz.vi 423
$cats = array();
719 mateusz.vi 424
 
909 mateusz.vi 425
// ******** compute the version-sorted list of packages with a single *********
426
// ******** description and category list for each package ********************
427
 
719 mateusz.vi 428
// iterate over each svp package
429
foreach ($pkgdb as $pkg => $versions) {
430
 
431
  // sort filenames by version, highest first
912 mateusz.vi 432
  uksort($versions, "dos_version_compare");
719 mateusz.vi 433
  $versions = array_reverse($versions, true);
434
 
435
  foreach ($versions as $ver => $meta) {
436
    $fname = $meta['fname'];
437
    $desc = $meta['desc'];
438
 
439
    $bsum = file2bsum(realpath($repodir . '/' . $fname));
440
 
441
    $meta2['ver'] = strval($ver);
442
    $meta2['bsum'] = $bsum;
443
 
444
    if (empty($db[$pkg]['desc'])) $db[$pkg]['desc'] = $desc;
909 mateusz.vi 445
    if (empty($db[$pkg]['cats'])) {
446
      $db[$pkg]['cats'] = $meta['cats'];
447
      $cats = array_unique(array_merge($cats, $meta['cats']));
448
    }
719 mateusz.vi 449
    $db[$pkg]['versions'][$fname] = $meta2;
450
  }
451
 
562 mateuszvis 452
  $pkgcount++;
453
 
454
}
455
 
719 mateusz.vi 456
if ($pkgcount < 100) echo "WARNING: an unexpectedly low number of packages has been found in the repo ({$pkgcount})\n";
562 mateuszvis 457
 
801 mateusz.vi 458
$json_blob = json_encode($db);
459
if ($json_blob === false) {
460
  echo "ERROR: JSON convertion failed! -> ";
461
  switch (json_last_error()) {
462
    case JSON_ERROR_DEPTH:
463
      echo 'maximum stack depth exceeded';
464
      break;
465
    case JSON_ERROR_STATE_MISMATCH:
466
      echo 'underflow of the modes mismatch';
467
      break;
468
    case JSON_ERROR_CTRL_CHAR:
469
      echo 'unexpected control character found';
470
      break;
471
    case JSON_ERROR_UTF8:
472
      echo 'malformed utf-8 characters';
473
      break;
474
    default:
475
      echo "unknown error";
476
      break;
477
  }
478
  echo "\n";
479
}
480
 
909 mateusz.vi 481
file_put_contents($repodir . '/_index.json', $json_blob);
562 mateuszvis 482
 
909 mateusz.vi 483
$cats_json = json_encode($cats);
484
file_put_contents($repodir . '/_cats.json', $cats_json);
485
 
562 mateuszvis 486
exit(0);
487
 
488
?>