Subversion Repositories SvarDOS

Rev

Rev 909 | Rev 914 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 909 Rev 912
1
<?php /*
1
<?php /*
2
 
2
 
3
  SvarDOS repo index builder
3
  SvarDOS repo index builder
4
  Copyright (C) Mateusz Viste 2012-2022
4
  Copyright (C) Mateusz Viste 2012-2022
5
 
5
 
6
  buildidx computes an index json file for the SvarDOS repository.
6
  buildidx computes an index json file for the SvarDOS repository.
7
  it must be executed pointing to a directory that stores packages (*.svp)
7
  it must be executed pointing to a directory that stores packages (*.svp)
8
  files. buildidx will generate the index file and save it into the package
8
  files. buildidx will generate the index file and save it into the package
9
  repository.
9
  repository.
10
 
10
 
11
  requires php-zip
11
  requires php-zip
12
 
12
 
13
  21 feb 2022: buildidx collects categories looking at the dir layout of each package
13
  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)
14
  17 feb 2022: checking for non-8+3 filenames in packages and duplicates + devload no longer part of CORE
14
  17 feb 2022: checking for non-8+3 filenames in packages and duplicates + devload no longer part of CORE
15
  16 feb 2022: added warning about overlong version strings and wild files location
15
  16 feb 2022: added warning about overlong version strings and wild files location
16
  15 feb 2022: index is generated as json, contains all filenames and alt versions
16
  15 feb 2022: index is generated as json, contains all filenames and alt versions
17
  14 feb 2022: packages are expected to have the *.svp extension
17
  14 feb 2022: packages are expected to have the *.svp extension
18
  12 feb 2022: skip source packages from being processed (*.src.zip)
18
  12 feb 2022: skip source packages from being processed (*.src.zip)
19
  20 jan 2022: rewritten the code from ANSI C to PHP for easier maintenance
19
  20 jan 2022: rewritten the code from ANSI C to PHP for easier maintenance
20
  13 feb 2021: 'title' LSM field is no longer looked after
20
  13 feb 2021: 'title' LSM field is no longer looked after
21
  11 feb 2021: lsm headers are no longer checked, so it is compatible with the simpler lsm format used by SvarDOS
21
  11 feb 2021: lsm headers are no longer checked, so it is compatible with the simpler lsm format used by SvarDOS
22
  13 jan 2021: removed the identification line, changed CRC32 to bsum, not creating the listing.txt file and stopped compressing index
22
  13 jan 2021: removed the identification line, changed CRC32 to bsum, not creating the listing.txt file and stopped compressing index
23
  23 apr 2017: uncompressed index is no longer created, added CRC32 of zib (bin only) files, if present
23
  23 apr 2017: uncompressed index is no longer created, added CRC32 of zib (bin only) files, if present
24
  28 aug 2016: listing.txt is always written inside the repo dir (instead of inside current dir)
24
  28 aug 2016: listing.txt is always written inside the repo dir (instead of inside current dir)
25
  27 aug 2016: accepting full paths to repos (starting with /...)
25
  27 aug 2016: accepting full paths to repos (starting with /...)
26
  07 dec 2013: rewritten buildidx in ANSI C89
26
  07 dec 2013: rewritten buildidx in ANSI C89
27
  19 aug 2013: add a compressed version of the index file to repos (index.gz)
27
  19 aug 2013: add a compressed version of the index file to repos (index.gz)
28
  22 jul 2013: creating a listing.txt file with list of packages
28
  22 jul 2013: creating a listing.txt file with list of packages
29
  18 jul 2013: writing the number of packaged into the first line of the lst file
29
  18 jul 2013: writing the number of packaged into the first line of the lst file
30
  11 jul 2013: added a switch to 7za to make it case insensitive when extracting lsm files
30
  11 jul 2013: added a switch to 7za to make it case insensitive when extracting lsm files
31
  10 jul 2013: changed unzip calls to 7za (to handle cases when appinfo is compressed with lzma)
31
  10 jul 2013: changed unzip calls to 7za (to handle cases when appinfo is compressed with lzma)
32
  04 feb 2013: added CRC32 support
32
  04 feb 2013: added CRC32 support
33
  22 sep 2012: forked 1st version from FDUPDATE builder
33
  22 sep 2012: forked 1st version from FDUPDATE builder
34
*/
34
*/
35
 
35
 
36
$PVER = "20220221";
36
$PVER = "20220221";
37
 
37
 
38
 
38
 
39
// computes the BSD sum of a file and returns it
39
// computes the BSD sum of a file and returns it
40
function file2bsum($fname) {
40
function file2bsum($fname) {
41
  $result = 0;
41
  $result = 0;
42
 
42
 
43
  $fd = fopen($fname, 'rb');
43
  $fd = fopen($fname, 'rb');
44
  if ($fd === false) return(0);
44
  if ($fd === false) return(0);
45
 
45
 
46
  while (!feof($fd)) {
46
  while (!feof($fd)) {
47
 
47
 
48
    $buff = fread($fd, 1024 * 1024);
48
    $buff = fread($fd, 1024 * 1024);
49
 
49
 
50
    $slen = strlen($buff);
50
    $slen = strlen($buff);
51
    for ($i = 0; $i < $slen; $i++) {
51
    for ($i = 0; $i < $slen; $i++) {
52
      // rotr
52
      // rotr
53
      $result = ($result >> 1) | ($result << 15);
53
      $result = ($result >> 1) | ($result << 15);
54
      // add and truncate to 16 bits
54
      // add and truncate to 16 bits
55
      $result += ord($buff[$i]);
55
      $result += ord($buff[$i]);
56
      $result &= 0xffff;
56
      $result &= 0xffff;
57
    }
57
    }
58
  }
58
  }
59
 
59
 
60
  fclose($fd);
60
  fclose($fd);
61
  return($result);
61
  return($result);
62
}
62
}
63
 
63
 
64
 
64
 
-
 
65
// translates a version string into a array of integer values.
-
 
66
// Accepted formats follow:
-
 
67
//    300.12.1
-
 
68
//    1
-
 
69
//    12.2.34.2-4.5
-
 
70
//    1.2c
-
 
71
//    1.01 beta+3
-
 
72
//    2013-12-31
-
 
73
//    20220222 alpha
-
 
74
function vertoarr($verstr) {
-
 
75
  $subver = array(0,0,0,0);
-
 
76
 
-
 
77
  // switch string to lcase for easier processing and trim any leading or trailing white spaces
-
 
78
  $verstr = strtolower(trim($verstr));
-
 
79
 
-
 
80
  // replace all '-' and '/' characters to '.' (uniformization of sub-version parts delimiters)
-
 
81
  $verstr = strtr($verstr, '-/', '..');
-
 
82
 
-
 
83
  // is there a subversion value? (for example "+4" in "1.05+4")
-
 
84
  $i = strrpos($verstr, '+', 1);
-
 
85
  if ($i !== false) {
-
 
86
    // validate the svar-version is a proper integer
-
 
87
    $svarver = substr($verstr, $i + 1);
-
 
88
    if (! preg_match('/[1-9][0-9]*/', $svarver)) {
-
 
89
      return(false);
-
 
90
    }
-
 
91
    $subver[3] = intval($svarver); // set the +rev as a very minor item
-
 
92
    $verstr = substr($verstr, 0, $i);
-
 
93
  }
-
 
94
 
-
 
95
  // is the version ending with ' alpha', 'beta'?
-
 
96
  if (preg_match('/ (alpha|beta)$/', $verstr)) {
-
 
97
    $i = strrpos($verstr, ' ');
-
 
98
    $greek = substr($verstr, $i + 1);
-
 
99
    $verstr = trim(substr($verstr, 0, $i));
-
 
100
    if ($greek == 'alpha') {
-
 
101
      $subver[2] = 1;
-
 
102
    } else if ($greek == 'beta') {
-
 
103
      $subver[2] = 2;
-
 
104
    } else {
-
 
105
      return(false);
-
 
106
    }
-
 
107
  }
-
 
108
 
-
 
109
  // does the version string have a single-letter subversion? (1.0c)
-
 
110
  if (preg_match('/[a-z]$/', $verstr)) {
-
 
111
    $subver[1] = ord(substr($verstr, -1));
-
 
112
    $verstr = substr_replace($verstr, '', -1); // remove last character from string
-
 
113
  }
-
 
114
 
-
 
115
  // validate the format is supported, should be something no more complex than 1.05.3.33
-
 
116
  if (! preg_match('/[0-9][0-9.]{0,20}/', $verstr)) {
-
 
117
    return(false);
-
 
118
  }
-
 
119
 
-
 
120
  // NOTE: a zero right after a separator and trailed with a digit (as in 1.01)
-
 
121
  //       has a special meaning
-
 
122
  $exploded = explode('.', $verstr);
-
 
123
  if (count($exploded) > 16) {
-
 
124
    return(false);
-
 
125
  }
-
 
126
  $exploded[16] = $subver[0]; // unused yet
-
 
127
  $exploded[17] = $subver[1]; // a-z (1.0c)
-
 
128
  $exploded[18] = $subver[2]; // alpha/beta
-
 
129
  $exploded[19] = $subver[3]; // svar-ver (1.0+5)
-
 
130
  for ($i = 0; $i < 20; $i++) if (empty($exploded[$i])) $exploded[$i] = '0';
-
 
131
 
-
 
132
  ksort($exploded);
-
 
133
 
-
 
134
  return($exploded);
-
 
135
}
-
 
136
 
-
 
137
 
-
 
138
function dos_version_compare($v1, $v2) {
-
 
139
  $v1arr = vertoarr($v1);
-
 
140
  $v2arr = vertoarr($v2);
-
 
141
  for ($i = 0; $i < count($v1arr); $i++) {
-
 
142
    $r = strcmp($v1arr[$i], $v2arr[$i]);
-
 
143
    if ($r != 0) return($r);
-
 
144
  }
-
 
145
  return(0);
-
 
146
}
-
 
147
 
-
 
148
 
65
// reads file fil from zip archive z and returns its content, or false on error
149
// reads file fil from zip archive z and returns its content, or false on error
66
function read_file_from_zip($z, $fil) {
150
function read_file_from_zip($z, $fil) {
67
  $zip = new ZipArchive;
151
  $zip = new ZipArchive;
68
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
152
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
69
    echo "ERROR: failed to open zip file '{$z}'\n";
153
    echo "ERROR: failed to open zip file '{$z}'\n";
70
    return(false);
154
    return(false);
71
  }
155
  }
72
 
156
 
73
  // load the appinfo/pkgname.lsm file
157
  // load the appinfo/pkgname.lsm file
74
  $res = $zip->getFromName($fil, 8192, ZipArchive::FL_NOCASE);
158
  $res = $zip->getFromName($fil, 8192, ZipArchive::FL_NOCASE);
75
 
159
 
76
  $zip->close();
160
  $zip->close();
77
  return($res);
161
  return($res);
78
}
162
}
79
 
163
 
80
 
164
 
81
function read_list_of_files_in_zip($z) {
165
function read_list_of_files_in_zip($z) {
82
  $zip = new ZipArchive;
166
  $zip = new ZipArchive;
83
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
167
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
84
    echo "ERROR: failed to open zip file '{$z}'\n";
168
    echo "ERROR: failed to open zip file '{$z}'\n";
85
    return(false);
169
    return(false);
86
  }
170
  }
87
 
171
 
88
  $res = array();
172
  $res = array();
89
  for ($i = 0; $i < $zip->numFiles; $i++) $res[] = $zip->getNameIndex($i);
173
  for ($i = 0; $i < $zip->numFiles; $i++) $res[] = $zip->getNameIndex($i);
90
 
174
 
91
  $zip->close();
175
  $zip->close();
92
  return($res);
176
  return($res);
93
}
177
}
94
 
178
 
95
 
179
 
96
// reads a LSM string and returns it in the form of an array
180
// reads a LSM string and returns it in the form of an array
97
function parse_lsm($s) {
181
function parse_lsm($s) {
98
  $res = array();
182
  $res = array();
99
  for ($l = strtok($s, "\n"); $l !== false; $l = strtok("\n")) {
183
  for ($l = strtok($s, "\n"); $l !== false; $l = strtok("\n")) {
100
    // the line is "token: value", let's find the colon
184
    // the line is "token: value", let's find the colon
101
    $colpos = strpos($l, ':');
185
    $colpos = strpos($l, ':');
102
    if (($colpos === false) || ($colpos === 0)) continue;
186
    if (($colpos === false) || ($colpos === 0)) continue;
103
    $tok = strtolower(trim(substr($l, 0, $colpos)));
187
    $tok = strtolower(trim(substr($l, 0, $colpos)));
104
    $val = trim(substr($l, $colpos + 1));
188
    $val = trim(substr($l, $colpos + 1));
105
    $res[$tok] = $val;
189
    $res[$tok] = $val;
106
  }
190
  }
107
  return($res);
191
  return($res);
108
}
192
}
109
 
193
 
110
 
194
 
111
// on PHP 8+ there is str_starts_with(), but not on PHP 7 so I use this
195
// on PHP 8+ there is str_starts_with(), but not on PHP 7 so I use this
112
function str_head_is($haystack, $needle) {
196
function str_head_is($haystack, $needle) {
113
  return strpos($haystack, $needle) === 0;
197
  return strpos($haystack, $needle) === 0;
114
}
198
}
115
 
199
 
116
 
200
 
117
// returns an array that contains CORE packages (populated from the core subdirectory in pkgdir)
201
// returns an array that contains CORE packages (populated from the core subdirectory in pkgdir)
118
function load_core_list($repodir) {
202
function load_core_list($repodir) {
119
  $res = array();
203
  $res = array();
120
 
204
 
121
  foreach (scandir($repodir . '/core/') as $f) {
205
  foreach (scandir($repodir . '/core/') as $f) {
122
    if (!preg_match('/\.svp$/', $f)) continue;
206
    if (!preg_match('/\.svp$/', $f)) continue;
123
    $res[] = explode('.', $f)[0];
207
    $res[] = explode('.', $f)[0];
124
  }
208
  }
125
  return($res);
209
  return($res);
126
}
210
}
127
 
211
 
128
 
212
 
129
// ***************** MAIN ROUTINE *********************************************
213
// ***************** MAIN ROUTINE *********************************************
130
 
214
 
131
//echo "SvarDOS repository index generator ver {$PVER}\n";
215
//echo "SvarDOS repository index generator ver {$PVER}\n";
132
 
216
 
133
if (($_SERVER['argc'] != 2) || ($_SERVER['argv'][1][0] == '-')) {
217
if (($_SERVER['argc'] != 2) || ($_SERVER['argv'][1][0] == '-')) {
134
  echo "usage: php buildidx.php repodir\n";
218
  echo "usage: php buildidx.php repodir\n";
135
  exit(1);
219
  exit(1);
136
}
220
}
137
 
221
 
138
$repodir = $_SERVER['argv'][1];
222
$repodir = $_SERVER['argv'][1];
139
 
223
 
140
$pkgfiles = scandir($repodir);
224
$pkgfiles = scandir($repodir);
141
$pkgcount = 0;
225
$pkgcount = 0;
142
 
226
 
143
 
227
 
144
// load the list of CORE and MSDOS_COMPAT packages
228
// load the list of CORE and MSDOS_COMPAT packages
145
 
229
 
146
$core_packages_list = load_core_list($repodir);
230
$core_packages_list = load_core_list($repodir);
147
$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');
231
$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');
148
 
232
 
149
// do a list of all svp packages with their available versions and descriptions
233
// do a list of all svp packages with their available versions and descriptions
150
 
234
 
151
$pkgdb = array();
235
$pkgdb = array();
152
foreach ($pkgfiles as $fname) {
236
foreach ($pkgfiles as $fname) {
153
  if (!preg_match('/\.svp$/i', $fname)) continue; // skip non-svp files
237
  if (!preg_match('/\.svp$/i', $fname)) continue; // skip non-svp files
154
 
238
 
155
  if (!preg_match('/^[a-zA-Z0-9+. _-]*\.svp$/', $fname)) {
239
  if (!preg_match('/^[a-zA-Z0-9+. _-]*\.svp$/', $fname)) {
156
    echo "ERROR: {$fname} has a very weird name\n";
240
    echo "ERROR: {$fname} has a very weird name\n";
157
    continue;
241
    continue;
158
  }
242
  }
159
 
243
 
160
  $path_parts = pathinfo($fname);
244
  $path_parts = pathinfo($fname);
161
  $pkgnam = explode('-', $path_parts['filename'])[0];
245
  $pkgnam = explode('-', $path_parts['filename'])[0];
162
  $pkgfullpath = realpath($repodir . '/' . $fname);
246
  $pkgfullpath = realpath($repodir . '/' . $fname);
163
 
247
 
164
  $lsm = read_file_from_zip($pkgfullpath, "appinfo/{$pkgnam}.lsm");
248
  $lsm = read_file_from_zip($pkgfullpath, "appinfo/{$pkgnam}.lsm");
165
  if ($lsm == false) {
249
  if ($lsm == false) {
166
    echo "ERROR: {$fname} does not contain an LSM file at the expected location\n";
250
    echo "ERROR: {$fname} does not contain an LSM file at the expected location\n";
167
    continue;
251
    continue;
168
  }
252
  }
169
  $lsmarray = parse_lsm($lsm);
253
  $lsmarray = parse_lsm($lsm);
170
  if (empty($lsmarray['version'])) {
254
  if (empty($lsmarray['version'])) {
171
    echo "ERROR: lsm file in {$fname} does not contain a version\n";
255
    echo "ERROR: lsm file in {$fname} does not contain a version\n";
172
    continue;
256
    continue;
173
  }
257
  }
174
  if (strlen($lsmarray['version']) > 16) {
258
  if (strlen($lsmarray['version']) > 16) {
175
    echo "ERROR: version string in lsm file of {$fname} is too long (16 chars max)\n";
259
    echo "ERROR: version string in lsm file of {$fname} is too long (16 chars max)\n";
176
    continue;
260
    continue;
177
  }
261
  }
178
  if (empty($lsmarray['description'])) {
262
  if (empty($lsmarray['description'])) {
179
    echo "ERROR: lsm file in {$fname} does not contain a description\n";
263
    echo "ERROR: lsm file in {$fname} does not contain a description\n";
180
    continue;
264
    continue;
181
  }
265
  }
182
 
266
 
183
  // validate the files present in the archive
267
  // validate the files present in the archive
184
  $listoffiles = read_list_of_files_in_zip($pkgfullpath);
268
  $listoffiles = read_list_of_files_in_zip($pkgfullpath);
185
  $pkgdir = $pkgnam;
269
  $pkgdir = $pkgnam;
186
 
270
 
187
  // special rule for "parent and children" packages
271
  // special rule for "parent and children" packages
188
  if (str_head_is($pkgnam, 'djgpp_')) $pkgdir = 'djgpp'; // djgpp_* packages put their files in djgpp
272
  if (str_head_is($pkgnam, 'djgpp_')) $pkgdir = 'djgpp'; // djgpp_* packages put their files in djgpp
189
  if ($pkgnam == 'fbc_help') $pkgdir = 'fbc'; // FreeBASIC help goes to the FreeBASIC dir
273
  if ($pkgnam == 'fbc_help') $pkgdir = 'fbc'; // FreeBASIC help goes to the FreeBASIC dir
190
  if ($pkgnam == 'clamdb') $pkgdir = 'clamav'; // data patterns for clamav
274
  if ($pkgnam == 'clamdb') $pkgdir = 'clamav'; // data patterns for clamav
191
 
275
 
192
  // array used to detect duplicated entries after lower-case conversion
276
  // array used to detect duplicated entries after lower-case conversion
193
  $duparr = array();
277
  $duparr = array();
194
 
278
 
195
  // will hold the list of categories that this package belongs to
279
  // will hold the list of categories that this package belongs to
196
  $catlist = array();
280
  $catlist = array();
197
 
281
 
198
  foreach ($listoffiles as $f) {
282
  foreach ($listoffiles as $f) {
199
    $f = strtolower($f);
283
    $f = strtolower($f);
200
    $path_array = explode('/', $f);
284
    $path_array = explode('/', $f);
201
    // emit a warning when non-8+3 filenames are spotted and find duplicates
285
    // emit a warning when non-8+3 filenames are spotted and find duplicates
202
    foreach ($path_array as $item) {
286
    foreach ($path_array as $item) {
203
      if (empty($item)) continue; // skip empty items at end of paths (eg. appinfo/)
287
      if (empty($item)) continue; // skip empty items at end of paths (eg. appinfo/)
204
      if (!preg_match("/[a-z0-9!#$%&'()@^_`{}~-]{1,8}(\.[a-z0-9!#$%&'()@^_`{}~-]{1,3}){0,1}/", $item)) {
288
      if (!preg_match("/[a-z0-9!#$%&'()@^_`{}~-]{1,8}(\.[a-z0-9!#$%&'()@^_`{}~-]{1,3}){0,1}/", $item)) {
205
        echo "WARNING: {$fname} contains a non-8+3 path (or weird char): {$item} (in $f)\n";
289
        echo "WARNING: {$fname} contains a non-8+3 path (or weird char): {$item} (in $f)\n";
206
      }
290
      }
207
    }
291
    }
208
    // look for dups
292
    // look for dups
209
    if (array_search($f, $duparr) !== false) {
293
    if (array_search($f, $duparr) !== false) {
210
      echo "WARNING: {$fname} contains a duplicated entry: '{$f}'\n";
294
      echo "WARNING: {$fname} contains a duplicated entry: '{$f}'\n";
211
    } else {
295
    } else {
212
      $duparr[] = $f;
296
      $duparr[] = $f;
213
    }
297
    }
214
    // LSM file is ok
298
    // LSM file is ok
215
    if ($f === "appinfo/{$pkgnam}.lsm") continue;
299
    if ($f === "appinfo/{$pkgnam}.lsm") continue;
216
    if ($f === "appinfo/") continue;
300
    if ($f === "appinfo/") continue;
217
    // CORE and MSDOS_COMPAT packages are premium citizens and can do a little more
301
    // CORE and MSDOS_COMPAT packages are premium citizens and can do a little more
218
    $core_or_msdoscompat = 0;
302
    $core_or_msdoscompat = 0;
219
    if (array_search($pkgnam, $core_packages_list) !== false) {
303
    if (array_search($pkgnam, $core_packages_list) !== false) {
220
      $catlist[] = 'core';
304
      $catlist[] = 'core';
221
      $core_or_msdoscompat = 1;
305
      $core_or_msdoscompat = 1;
222
    }
306
    }
223
    if (array_search($pkgnam, $msdos_compat_list) !== false) {
307
    if (array_search($pkgnam, $msdos_compat_list) !== false) {
224
      $catlist[] = 'msdos_compat';
308
      $catlist[] = 'msdos_compat';
225
      $core_or_msdoscompat = 1;
309
      $core_or_msdoscompat = 1;
226
    }
310
    }
227
    if ($core_or_msdoscompat == 1) {
311
    if ($core_or_msdoscompat == 1) {
228
      if (str_head_is($f, 'bin/')) continue;
312
      if (str_head_is($f, 'bin/')) continue;
229
      if (str_head_is($f, 'cpi/')) continue;
313
      if (str_head_is($f, 'cpi/')) continue;
230
      if (str_head_is($f, "doc/{$pkgdir}/")) continue;
314
      if (str_head_is($f, "doc/{$pkgdir}/")) continue;
231
      if ($f === 'doc/') continue;
315
      if ($f === 'doc/') continue;
232
      if (str_head_is($f, "nls/{$pkgdir}.")) continue;
316
      if (str_head_is($f, "nls/{$pkgdir}.")) continue;
233
      if ($f === 'nls/') continue;
317
      if ($f === 'nls/') continue;
234
    }
318
    }
235
    // the help package is allowed to put files in... help
319
    // the help package is allowed to put files in... help
236
    if (($pkgnam == 'help') && (str_head_is($f, 'help/'))) continue;
320
    if (($pkgnam == 'help') && (str_head_is($f, 'help/'))) continue;
237
    // must be category-prefixed file, add it to the list of categories for this package
321
    // must be category-prefixed file, add it to the list of categories for this package
238
    $catlist[] = explode('/', $f)[0];
322
    $catlist[] = explode('/', $f)[0];
239
    // well-known "category" dirs are okay
323
    // well-known "category" dirs are okay
240
    if (str_head_is($f, "progs/{$pkgdir}/")) continue;
324
    if (str_head_is($f, "progs/{$pkgdir}/")) continue;
241
    if ($f === 'progs/') continue;
325
    if ($f === 'progs/') continue;
242
    if (str_head_is($f, "devel/{$pkgdir}/")) continue;
326
    if (str_head_is($f, "devel/{$pkgdir}/")) continue;
243
    if ($f === 'devel/') continue;
327
    if ($f === 'devel/') continue;
244
    if (str_head_is($f, "games/{$pkgdir}/")) continue;
328
    if (str_head_is($f, "games/{$pkgdir}/")) continue;
245
    if ($f === 'games/') continue;
329
    if ($f === 'games/') continue;
246
    if (str_head_is($f, "drivers/{$pkgdir}/")) continue;
330
    if (str_head_is($f, "drivers/{$pkgdir}/")) continue;
247
    if ($f === 'drivers/') continue;
331
    if ($f === 'drivers/') continue;
248
    echo "WARNING: {$fname} contains a file in an illegal location: {$f}\n";
332
    echo "WARNING: {$fname} contains a file in an illegal location: {$f}\n";
249
  }
333
  }
250
 
334
 
-
 
335
  // do I understand the version string?
-
 
336
  if (vertoarr($lsmarray['version']) === false) echo "WARNING: {$fname} parsing of version string failed ('{$lsmarray['version']}')\n";
-
 
337
 
251
  $meta['fname'] = $fname;
338
  $meta['fname'] = $fname;
252
  $meta['desc'] = $lsmarray['description'];
339
  $meta['desc'] = $lsmarray['description'];
253
  $meta['cats'] = array_unique($catlist);
340
  $meta['cats'] = array_unique($catlist);
254
 
341
 
255
  $pkgdb[$pkgnam][$lsmarray['version']] = $meta;
342
  $pkgdb[$pkgnam][$lsmarray['version']] = $meta;
256
}
343
}
257
 
344
 
258
 
345
 
259
$db = array();
346
$db = array();
260
$cats = array();
347
$cats = array();
261
 
348
 
262
// ******** compute the version-sorted list of packages with a single *********
349
// ******** compute the version-sorted list of packages with a single *********
263
// ******** description and category list for each package ********************
350
// ******** description and category list for each package ********************
264
 
351
 
265
// iterate over each svp package
352
// iterate over each svp package
266
foreach ($pkgdb as $pkg => $versions) {
353
foreach ($pkgdb as $pkg => $versions) {
267
 
354
 
268
  // sort filenames by version, highest first
355
  // sort filenames by version, highest first
269
  uksort($versions, "version_compare");
356
  uksort($versions, "dos_version_compare");
270
  $versions = array_reverse($versions, true);
357
  $versions = array_reverse($versions, true);
271
 
358
 
272
  foreach ($versions as $ver => $meta) {
359
  foreach ($versions as $ver => $meta) {
273
    $fname = $meta['fname'];
360
    $fname = $meta['fname'];
274
    $desc = $meta['desc'];
361
    $desc = $meta['desc'];
275
 
362
 
276
    $bsum = file2bsum(realpath($repodir . '/' . $fname));
363
    $bsum = file2bsum(realpath($repodir . '/' . $fname));
277
 
364
 
278
    $meta2['ver'] = strval($ver);
365
    $meta2['ver'] = strval($ver);
279
    $meta2['bsum'] = $bsum;
366
    $meta2['bsum'] = $bsum;
280
 
367
 
281
    if (empty($db[$pkg]['desc'])) $db[$pkg]['desc'] = $desc;
368
    if (empty($db[$pkg]['desc'])) $db[$pkg]['desc'] = $desc;
282
    if (empty($db[$pkg]['cats'])) {
369
    if (empty($db[$pkg]['cats'])) {
283
      $db[$pkg]['cats'] = $meta['cats'];
370
      $db[$pkg]['cats'] = $meta['cats'];
284
      $cats = array_unique(array_merge($cats, $meta['cats']));
371
      $cats = array_unique(array_merge($cats, $meta['cats']));
285
    }
372
    }
286
    $db[$pkg]['versions'][$fname] = $meta2;
373
    $db[$pkg]['versions'][$fname] = $meta2;
287
  }
374
  }
288
 
375
 
289
  $pkgcount++;
376
  $pkgcount++;
290
 
377
 
291
}
378
}
292
 
379
 
293
if ($pkgcount < 100) echo "WARNING: an unexpectedly low number of packages has been found in the repo ({$pkgcount})\n";
380
if ($pkgcount < 100) echo "WARNING: an unexpectedly low number of packages has been found in the repo ({$pkgcount})\n";
294
 
381
 
295
$json_blob = json_encode($db);
382
$json_blob = json_encode($db);
296
if ($json_blob === false) {
383
if ($json_blob === false) {
297
  echo "ERROR: JSON convertion failed! -> ";
384
  echo "ERROR: JSON convertion failed! -> ";
298
  switch (json_last_error()) {
385
  switch (json_last_error()) {
299
    case JSON_ERROR_DEPTH:
386
    case JSON_ERROR_DEPTH:
300
      echo 'maximum stack depth exceeded';
387
      echo 'maximum stack depth exceeded';
301
      break;
388
      break;
302
    case JSON_ERROR_STATE_MISMATCH:
389
    case JSON_ERROR_STATE_MISMATCH:
303
      echo 'underflow of the modes mismatch';
390
      echo 'underflow of the modes mismatch';
304
      break;
391
      break;
305
    case JSON_ERROR_CTRL_CHAR:
392
    case JSON_ERROR_CTRL_CHAR:
306
      echo 'unexpected control character found';
393
      echo 'unexpected control character found';
307
      break;
394
      break;
308
    case JSON_ERROR_UTF8:
395
    case JSON_ERROR_UTF8:
309
      echo 'malformed utf-8 characters';
396
      echo 'malformed utf-8 characters';
310
      break;
397
      break;
311
    default:
398
    default:
312
      echo "unknown error";
399
      echo "unknown error";
313
      break;
400
      break;
314
  }
401
  }
315
  echo "\n";
402
  echo "\n";
316
}
403
}
317
 
404
 
318
file_put_contents($repodir . '/_index.json', $json_blob);
405
file_put_contents($repodir . '/_index.json', $json_blob);
319
 
406
 
320
$cats_json = json_encode($cats);
407
$cats_json = json_encode($cats);
321
file_put_contents($repodir . '/_cats.json', $cats_json);
408
file_put_contents($repodir . '/_cats.json', $cats_json);
322
 
409
 
323
exit(0);
410
exit(0);
324
 
411
 
325
?>
412
?>
326
 
413