Subversion Repositories SvarDOS

Rev

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