Subversion Repositories SvarDOS

Rev

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

Rev 921 Rev 922
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 + improved version string parsing (replaced version_compare call by dos_version_compare)
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 = "20220222";
36
$PVER = "20220222";
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.
65
// translates a version string into a array of integer values.
66
// Accepted formats follow:
66
// Accepted formats follow:
67
//    300.12.1
67
//    300.12.1
68
//    1
68
//    1
69
//    12.2.34.2-4.5
69
//    12.2.34.2-4.5
70
//    1.2c
70
//    1.2c
71
//    1.01 beta+3
71
//    1.01 beta+3
72
//    2013-12-31
72
//    2013-12-31
73
//    20220222 alpha
73
//    20220222 alpha
74
function vertoarr($verstr) {
74
function vertoarr($verstr) {
75
  $subver = array(0,0,0,0);
75
  $subver = array(0,0,0,0);
76
 
76
 
77
  // switch string to lcase for easier processing and trim any leading or trailing white spaces
77
  // switch string to lcase for easier processing and trim any leading or trailing white spaces
78
  $verstr = strtolower(trim($verstr));
78
  $verstr = strtolower(trim($verstr));
79
 
79
 
80
  // replace all '-' and '/' characters to '.' (uniformization of sub-version parts delimiters)
80
  // replace all '-' and '/' characters to '.' (uniformization of sub-version parts delimiters)
81
  $verstr = strtr($verstr, '-/', '..');
81
  $verstr = strtr($verstr, '-/', '..');
82
 
82
 
83
  // is there a subversion value? (for example "+4" in "1.05+4")
83
  // is there a subversion value? (for example "+4" in "1.05+4")
84
  $i = strrpos($verstr, '+', 1);
84
  $i = strrpos($verstr, '+', 1);
85
  if ($i !== false) {
85
  if ($i !== false) {
86
    // validate the svar-version is a proper integer
86
    // validate the svar-version is a proper integer
87
    $svarver = substr($verstr, $i + 1);
87
    $svarver = substr($verstr, $i + 1);
88
    if (! preg_match('/[1-9][0-9]*/', $svarver)) {
88
    if (! preg_match('/[1-9][0-9]*/', $svarver)) {
89
      return(false);
89
      return(false);
90
    }
90
    }
91
    $subver[3] = intval($svarver); // set the +rev as a very minor item
91
    $subver[3] = intval($svarver); // set the +rev as a very minor item
92
    $verstr = substr($verstr, 0, $i);
92
    $verstr = substr($verstr, 0, $i);
93
  }
93
  }
94
 
94
 
95
  // is the version ending with ' alpha', 'beta', etc?
95
  // is the version ending with ' alpha', 'beta', etc?
96
  if (preg_match('/ (alpha|beta|gamma|delta|pre|rc)( [0-9]{1,4}){0,1}$/', $verstr)) {
96
  if (preg_match('/ (alpha|beta|gamma|delta|pre|rc|patch)( [0-9]{1,4}){0,1}$/', $verstr)) {
97
    // if there is a trailing beta-number, process it first
97
    // if there is a trailing beta-number, process it first
98
    if (preg_match('/ [0-9]{1,4}$/', $verstr)) {
98
    if (preg_match('/ [0-9]{1,4}$/', $verstr)) {
99
      $i = strrpos($verstr, ' ');
99
      $i = strrpos($verstr, ' ');
100
      $subver[2] = intval(substr($verstr, $i + 1));
100
      $subver[2] = intval(substr($verstr, $i + 1));
101
      $verstr = trim(substr($verstr, 0, $i));
101
      $verstr = trim(substr($verstr, 0, $i));
102
    }
102
    }
103
    $i = strrpos($verstr, ' ');
103
    $i = strrpos($verstr, ' ');
104
    $greek = substr($verstr, $i + 1);
104
    $greek = substr($verstr, $i + 1);
105
    $verstr = trim(substr($verstr, 0, $i));
105
    $verstr = trim(substr($verstr, 0, $i));
106
    if ($greek == 'alpha') {
106
    if ($greek == 'alpha') {
107
      $subver[1] = 1;
107
      $subver[1] = 1;
108
    } else if ($greek == 'beta') {
108
    } else if ($greek == 'beta') {
109
      $subver[1] = 2;
109
      $subver[1] = 2;
110
    } else if ($greek == 'gamma') {
110
    } else if ($greek == 'gamma') {
111
      $subver[1] = 3;
111
      $subver[1] = 3;
112
    } else if ($greek == 'delta') {
112
    } else if ($greek == 'delta') {
113
      $subver[1] = 4;
113
      $subver[1] = 4;
114
    } else if ($greek == 'pre') {
114
    } else if ($greek == 'pre') {
115
      $subver[1] = 5;
115
      $subver[1] = 5;
116
    } else if ($greek == 'rc') {
116
    } else if ($greek == 'rc') {
117
      $subver[1] = 6;
117
      $subver[1] = 6;
-
 
118
    } else if ($greek == 'patch') { // this is a POST-release version, as opposed to all above that are PRE-release versions
-
 
119
      $subver[1] = 99;
118
    } else {
120
    } else {
119
      return(false);
121
      return(false);
120
    }
122
    }
121
  } else {
123
  } else {
122
    $subver[1] = 99;
124
    $subver[1] = 98; // one less than the 'patch' level
123
  }
125
  }
124
 
126
 
125
  // does the version string have a single-letter subversion? (1.0c)
127
  // does the version string have a single-letter subversion? (1.0c)
126
  if (preg_match('/[a-z]$/', $verstr)) {
128
  if (preg_match('/[a-z]$/', $verstr)) {
127
    $subver[0] = ord(substr($verstr, -1));
129
    $subver[0] = ord(substr($verstr, -1));
128
    $verstr = substr_replace($verstr, '', -1); // remove last character from string
130
    $verstr = substr_replace($verstr, '', -1); // remove last character from string
129
  }
131
  }
130
 
132
 
131
  // validate the format is supported, should be something no more complex than 1.05.3.33
133
  // validate the format is supported, should be something no more complex than 1.05.3.33
132
  if (! preg_match('/^[0-9][0-9.]{0,20}$/', $verstr)) {
134
  if (! preg_match('/^[0-9][0-9.]{0,20}$/', $verstr)) {
133
    return(false);
135
    return(false);
134
  }
136
  }
135
 
137
 
136
  // NOTE: a zero right after a separator and trailed with a digit (as in 1.01)
138
  // NOTE: a zero right after a separator and trailed with a digit (as in 1.01)
137
  //       has a special meaning
139
  //       has a special meaning
138
  $exploded = explode('.', $verstr);
140
  $exploded = explode('.', $verstr);
139
  if (count($exploded) > 16) {
141
  if (count($exploded) > 16) {
140
    return(false);
142
    return(false);
141
  }
143
  }
142
  $exploded[16] = $subver[0]; // a-z (1.0c)
144
  $exploded[16] = $subver[0]; // a-z (1.0c)
143
  $exploded[17] = $subver[1]; // alpha/beta/gamma/delta/rc/pre
145
  $exploded[17] = $subver[1]; // alpha/beta/gamma/delta/rc/pre
144
  $exploded[18] = $subver[2]; // alpha-beta-gamma subversion (eg. "beta 9")
146
  $exploded[18] = $subver[2]; // alpha-beta-gamma subversion (eg. "beta 9")
145
  $exploded[19] = $subver[3]; // svar-ver (1.0+5)
147
  $exploded[19] = $subver[3]; // svar-ver (1.0+5)
146
  for ($i = 0; $i < 20; $i++) if (empty($exploded[$i])) $exploded[$i] = '0';
148
  for ($i = 0; $i < 20; $i++) if (empty($exploded[$i])) $exploded[$i] = '0';
147
 
149
 
148
  ksort($exploded);
150
  ksort($exploded);
149
 
151
 
150
  return($exploded);
152
  return($exploded);
151
}
153
}
152
 
154
 
153
 
155
 
154
function dos_version_compare($v1, $v2) {
156
function dos_version_compare($v1, $v2) {
155
  $v1arr = vertoarr($v1);
157
  $v1arr = vertoarr($v1);
156
  $v2arr = vertoarr($v2);
158
  $v2arr = vertoarr($v2);
157
  for ($i = 0; $i < count($v1arr); $i++) {
159
  for ($i = 0; $i < count($v1arr); $i++) {
158
    if ($v1arr[$i] > $v2arr[$i]) return(1);
160
    if ($v1arr[$i] > $v2arr[$i]) return(1);
159
    if ($v1arr[$i] < $v2arr[$i]) return(-1);
161
    if ($v1arr[$i] < $v2arr[$i]) return(-1);
160
  }
162
  }
161
  return(0);
163
  return(0);
162
}
164
}
163
 
165
 
164
 
166
 
165
// reads file fil from zip archive z and returns its content, or false on error
167
// reads file fil from zip archive z and returns its content, or false on error
166
function read_file_from_zip($z, $fil) {
168
function read_file_from_zip($z, $fil) {
167
  $zip = new ZipArchive;
169
  $zip = new ZipArchive;
168
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
170
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
169
    echo "ERROR: failed to open zip file '{$z}'\n";
171
    echo "ERROR: failed to open zip file '{$z}'\n";
170
    return(false);
172
    return(false);
171
  }
173
  }
172
 
174
 
173
  // load the appinfo/pkgname.lsm file
175
  // load the appinfo/pkgname.lsm file
174
  $res = $zip->getFromName($fil, 8192, ZipArchive::FL_NOCASE);
176
  $res = $zip->getFromName($fil, 8192, ZipArchive::FL_NOCASE);
175
 
177
 
176
  $zip->close();
178
  $zip->close();
177
  return($res);
179
  return($res);
178
}
180
}
179
 
181
 
180
 
182
 
181
function read_list_of_files_in_zip($z) {
183
function read_list_of_files_in_zip($z) {
182
  $zip = new ZipArchive;
184
  $zip = new ZipArchive;
183
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
185
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
184
    echo "ERROR: failed to open zip file '{$z}'\n";
186
    echo "ERROR: failed to open zip file '{$z}'\n";
185
    return(false);
187
    return(false);
186
  }
188
  }
187
 
189
 
188
  $res = array();
190
  $res = array();
189
  for ($i = 0; $i < $zip->numFiles; $i++) $res[] = $zip->getNameIndex($i);
191
  for ($i = 0; $i < $zip->numFiles; $i++) $res[] = $zip->getNameIndex($i);
190
 
192
 
191
  $zip->close();
193
  $zip->close();
192
  return($res);
194
  return($res);
193
}
195
}
194
 
196
 
195
 
197
 
196
// reads a LSM string and returns it in the form of an array
198
// reads a LSM string and returns it in the form of an array
197
function parse_lsm($s) {
199
function parse_lsm($s) {
198
  $res = array();
200
  $res = array();
199
  for ($l = strtok($s, "\n"); $l !== false; $l = strtok("\n")) {
201
  for ($l = strtok($s, "\n"); $l !== false; $l = strtok("\n")) {
200
    // the line is "token: value", let's find the colon
202
    // the line is "token: value", let's find the colon
201
    $colpos = strpos($l, ':');
203
    $colpos = strpos($l, ':');
202
    if (($colpos === false) || ($colpos === 0)) continue;
204
    if (($colpos === false) || ($colpos === 0)) continue;
203
    $tok = strtolower(trim(substr($l, 0, $colpos)));
205
    $tok = strtolower(trim(substr($l, 0, $colpos)));
204
    $val = trim(substr($l, $colpos + 1));
206
    $val = trim(substr($l, $colpos + 1));
205
    $res[$tok] = $val;
207
    $res[$tok] = $val;
206
  }
208
  }
207
  return($res);
209
  return($res);
208
}
210
}
209
 
211
 
210
 
212
 
211
// on PHP 8+ there is str_starts_with(), but not on PHP 7 so I use this
213
// on PHP 8+ there is str_starts_with(), but not on PHP 7 so I use this
212
function str_head_is($haystack, $needle) {
214
function str_head_is($haystack, $needle) {
213
  return strpos($haystack, $needle) === 0;
215
  return strpos($haystack, $needle) === 0;
214
}
216
}
215
 
217
 
216
 
218
 
217
// returns an array that contains CORE packages (populated from the core subdirectory in pkgdir)
219
// returns an array that contains CORE packages (populated from the core subdirectory in pkgdir)
218
function load_core_list($repodir) {
220
function load_core_list($repodir) {
219
  $res = array();
221
  $res = array();
220
 
222
 
221
  foreach (scandir($repodir . '/core/') as $f) {
223
  foreach (scandir($repodir . '/core/') as $f) {
222
    if (!preg_match('/\.svp$/', $f)) continue;
224
    if (!preg_match('/\.svp$/', $f)) continue;
223
    $res[] = explode('.', $f)[0];
225
    $res[] = explode('.', $f)[0];
224
  }
226
  }
225
  return($res);
227
  return($res);
226
}
228
}
227
 
229
 
228
 
230
 
229
// ***************** MAIN ROUTINE *********************************************
231
// ***************** MAIN ROUTINE *********************************************
230
 
232
 
231
//echo "SvarDOS repository index generator ver {$PVER}\n";
233
//echo "SvarDOS repository index generator ver {$PVER}\n";
232
 
234
 
233
if (($_SERVER['argc'] != 2) || ($_SERVER['argv'][1][0] == '-')) {
235
if (($_SERVER['argc'] != 2) || ($_SERVER['argv'][1][0] == '-')) {
234
  echo "usage: php buildidx.php repodir\n";
236
  echo "usage: php buildidx.php repodir\n";
235
  exit(1);
237
  exit(1);
236
}
238
}
237
 
239
 
238
$repodir = $_SERVER['argv'][1];
240
$repodir = $_SERVER['argv'][1];
239
 
241
 
240
$pkgfiles = scandir($repodir);
242
$pkgfiles = scandir($repodir);
241
$pkgcount = 0;
243
$pkgcount = 0;
242
 
244
 
243
 
245
 
244
// load the list of CORE and MSDOS_COMPAT packages
246
// load the list of CORE and MSDOS_COMPAT packages
245
 
247
 
246
$core_packages_list = load_core_list($repodir);
248
$core_packages_list = load_core_list($repodir);
247
$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');
249
$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');
248
 
250
 
249
// do a list of all svp packages with their available versions and descriptions
251
// do a list of all svp packages with their available versions and descriptions
250
 
252
 
251
$pkgdb = array();
253
$pkgdb = array();
252
foreach ($pkgfiles as $fname) {
254
foreach ($pkgfiles as $fname) {
253
  if (!preg_match('/\.svp$/i', $fname)) continue; // skip non-svp files
255
  if (!preg_match('/\.svp$/i', $fname)) continue; // skip non-svp files
254
 
256
 
255
  if (!preg_match('/^[a-zA-Z0-9+. _-]*\.svp$/', $fname)) {
257
  if (!preg_match('/^[a-zA-Z0-9+. _-]*\.svp$/', $fname)) {
256
    echo "ERROR: {$fname} has a very weird name\n";
258
    echo "ERROR: {$fname} has a very weird name\n";
257
    continue;
259
    continue;
258
  }
260
  }
259
 
261
 
260
  $path_parts = pathinfo($fname);
262
  $path_parts = pathinfo($fname);
261
  $pkgnam = explode('-', $path_parts['filename'])[0];
263
  $pkgnam = explode('-', $path_parts['filename'])[0];
262
  $pkgfullpath = realpath($repodir . '/' . $fname);
264
  $pkgfullpath = realpath($repodir . '/' . $fname);
263
 
265
 
264
  $lsm = read_file_from_zip($pkgfullpath, "appinfo/{$pkgnam}.lsm");
266
  $lsm = read_file_from_zip($pkgfullpath, "appinfo/{$pkgnam}.lsm");
265
  if ($lsm == false) {
267
  if ($lsm == false) {
266
    echo "ERROR: {$fname} does not contain an LSM file at the expected location\n";
268
    echo "ERROR: {$fname} does not contain an LSM file at the expected location\n";
267
    continue;
269
    continue;
268
  }
270
  }
269
  $lsmarray = parse_lsm($lsm);
271
  $lsmarray = parse_lsm($lsm);
270
  if (empty($lsmarray['version'])) {
272
  if (empty($lsmarray['version'])) {
271
    echo "ERROR: lsm file in {$fname} does not contain a version\n";
273
    echo "ERROR: lsm file in {$fname} does not contain a version\n";
272
    continue;
274
    continue;
273
  }
275
  }
274
  if (strlen($lsmarray['version']) > 16) {
276
  if (strlen($lsmarray['version']) > 16) {
275
    echo "ERROR: version string in lsm file of {$fname} is too long (16 chars max)\n";
277
    echo "ERROR: version string in lsm file of {$fname} is too long (16 chars max)\n";
276
    continue;
278
    continue;
277
  }
279
  }
278
  if (empty($lsmarray['description'])) {
280
  if (empty($lsmarray['description'])) {
279
    echo "ERROR: lsm file in {$fname} does not contain a description\n";
281
    echo "ERROR: lsm file in {$fname} does not contain a description\n";
280
    continue;
282
    continue;
281
  }
283
  }
282
 
284
 
283
  // validate the files present in the archive
285
  // validate the files present in the archive
284
  $listoffiles = read_list_of_files_in_zip($pkgfullpath);
286
  $listoffiles = read_list_of_files_in_zip($pkgfullpath);
285
  $pkgdir = $pkgnam;
287
  $pkgdir = $pkgnam;
286
 
288
 
287
  // special rule for "parent and children" packages
289
  // special rule for "parent and children" packages
288
  if (str_head_is($pkgnam, 'djgpp_')) $pkgdir = 'djgpp'; // djgpp_* packages put their files in djgpp
290
  if (str_head_is($pkgnam, 'djgpp_')) $pkgdir = 'djgpp'; // djgpp_* packages put their files in djgpp
289
  if ($pkgnam == 'fbc_help') $pkgdir = 'fbc'; // FreeBASIC help goes to the FreeBASIC dir
291
  if ($pkgnam == 'fbc_help') $pkgdir = 'fbc'; // FreeBASIC help goes to the FreeBASIC dir
290
  if ($pkgnam == 'clamdb') $pkgdir = 'clamav'; // data patterns for clamav
292
  if ($pkgnam == 'clamdb') $pkgdir = 'clamav'; // data patterns for clamav
291
 
293
 
292
  // array used to detect duplicated entries after lower-case conversion
294
  // array used to detect duplicated entries after lower-case conversion
293
  $duparr = array();
295
  $duparr = array();
294
 
296
 
295
  // will hold the list of categories that this package belongs to
297
  // will hold the list of categories that this package belongs to
296
  $catlist = array();
298
  $catlist = array();
297
 
299
 
298
  foreach ($listoffiles as $f) {
300
  foreach ($listoffiles as $f) {
299
    $f = strtolower($f);
301
    $f = strtolower($f);
300
    $path_array = explode('/', $f);
302
    $path_array = explode('/', $f);
301
    // emit a warning when non-8+3 filenames are spotted and find duplicates
303
    // emit a warning when non-8+3 filenames are spotted and find duplicates
302
    foreach ($path_array as $item) {
304
    foreach ($path_array as $item) {
303
      if (empty($item)) continue; // skip empty items at end of paths (eg. appinfo/)
305
      if (empty($item)) continue; // skip empty items at end of paths (eg. appinfo/)
304
      if (!preg_match("/[a-z0-9!#$%&'()@^_`{}~-]{1,8}(\.[a-z0-9!#$%&'()@^_`{}~-]{1,3}){0,1}/", $item)) {
306
      if (!preg_match("/[a-z0-9!#$%&'()@^_`{}~-]{1,8}(\.[a-z0-9!#$%&'()@^_`{}~-]{1,3}){0,1}/", $item)) {
305
        echo "WARNING: {$fname} contains a non-8+3 path (or weird char): {$item} (in $f)\n";
307
        echo "WARNING: {$fname} contains a non-8+3 path (or weird char): {$item} (in $f)\n";
306
      }
308
      }
307
    }
309
    }
308
    // look for dups
310
    // look for dups
309
    if (array_search($f, $duparr) !== false) {
311
    if (array_search($f, $duparr) !== false) {
310
      echo "WARNING: {$fname} contains a duplicated entry: '{$f}'\n";
312
      echo "WARNING: {$fname} contains a duplicated entry: '{$f}'\n";
311
    } else {
313
    } else {
312
      $duparr[] = $f;
314
      $duparr[] = $f;
313
    }
315
    }
314
    // LSM file is ok
316
    // LSM file is ok
315
    if ($f === "appinfo/{$pkgnam}.lsm") continue;
317
    if ($f === "appinfo/{$pkgnam}.lsm") continue;
316
    if ($f === "appinfo/") continue;
318
    if ($f === "appinfo/") continue;
317
    // CORE and MSDOS_COMPAT packages are premium citizens and can do a little more
319
    // CORE and MSDOS_COMPAT packages are premium citizens and can do a little more
318
    $core_or_msdoscompat = 0;
320
    $core_or_msdoscompat = 0;
319
    if (array_search($pkgnam, $core_packages_list) !== false) {
321
    if (array_search($pkgnam, $core_packages_list) !== false) {
320
      $catlist[] = 'core';
322
      $catlist[] = 'core';
321
      $core_or_msdoscompat = 1;
323
      $core_or_msdoscompat = 1;
322
    }
324
    }
323
    if (array_search($pkgnam, $msdos_compat_list) !== false) {
325
    if (array_search($pkgnam, $msdos_compat_list) !== false) {
324
      $catlist[] = 'msdos_compat';
326
      $catlist[] = 'msdos_compat';
325
      $core_or_msdoscompat = 1;
327
      $core_or_msdoscompat = 1;
326
    }
328
    }
327
    if ($core_or_msdoscompat == 1) {
329
    if ($core_or_msdoscompat == 1) {
328
      if (str_head_is($f, 'bin/')) continue;
330
      if (str_head_is($f, 'bin/')) continue;
329
      if (str_head_is($f, 'cpi/')) continue;
331
      if (str_head_is($f, 'cpi/')) continue;
330
      if (str_head_is($f, "doc/{$pkgdir}/")) continue;
332
      if (str_head_is($f, "doc/{$pkgdir}/")) continue;
331
      if ($f === 'doc/') continue;
333
      if ($f === 'doc/') continue;
332
      if (str_head_is($f, "nls/{$pkgdir}.")) continue;
334
      if (str_head_is($f, "nls/{$pkgdir}.")) continue;
333
      if ($f === 'nls/') continue;
335
      if ($f === 'nls/') continue;
334
    }
336
    }
335
    // the help package is allowed to put files in... help
337
    // the help package is allowed to put files in... help
336
    if (($pkgnam == 'help') && (str_head_is($f, 'help/'))) continue;
338
    if (($pkgnam == 'help') && (str_head_is($f, 'help/'))) continue;
337
    // must be category-prefixed file, add it to the list of categories for this package
339
    // must be category-prefixed file, add it to the list of categories for this package
338
    $catlist[] = explode('/', $f)[0];
340
    $catlist[] = explode('/', $f)[0];
339
    // well-known "category" dirs are okay
341
    // well-known "category" dirs are okay
340
    if (str_head_is($f, "progs/{$pkgdir}/")) continue;
342
    if (str_head_is($f, "progs/{$pkgdir}/")) continue;
341
    if ($f === 'progs/') continue;
343
    if ($f === 'progs/') continue;
342
    if (str_head_is($f, "devel/{$pkgdir}/")) continue;
344
    if (str_head_is($f, "devel/{$pkgdir}/")) continue;
343
    if ($f === 'devel/') continue;
345
    if ($f === 'devel/') continue;
344
    if (str_head_is($f, "games/{$pkgdir}/")) continue;
346
    if (str_head_is($f, "games/{$pkgdir}/")) continue;
345
    if ($f === 'games/') continue;
347
    if ($f === 'games/') continue;
346
    if (str_head_is($f, "drivers/{$pkgdir}/")) continue;
348
    if (str_head_is($f, "drivers/{$pkgdir}/")) continue;
347
    if ($f === 'drivers/') continue;
349
    if ($f === 'drivers/') continue;
348
    echo "WARNING: {$fname} contains a file in an illegal location: {$f}\n";
350
    echo "WARNING: {$fname} contains a file in an illegal location: {$f}\n";
349
  }
351
  }
350
 
352
 
351
  // do I understand the version string?
353
  // do I understand the version string?
352
  if (vertoarr($lsmarray['version']) === false) echo "WARNING: {$fname} parsing of version string failed ('{$lsmarray['version']}')\n";
354
  if (vertoarr($lsmarray['version']) === false) echo "WARNING: {$fname} parsing of version string failed ('{$lsmarray['version']}')\n";
353
 
355
 
354
  $meta['fname'] = $fname;
356
  $meta['fname'] = $fname;
355
  $meta['desc'] = $lsmarray['description'];
357
  $meta['desc'] = $lsmarray['description'];
356
  $meta['cats'] = array_unique($catlist);
358
  $meta['cats'] = array_unique($catlist);
357
 
359
 
358
  $pkgdb[$pkgnam][$lsmarray['version']] = $meta;
360
  $pkgdb[$pkgnam][$lsmarray['version']] = $meta;
359
}
361
}
360
 
362
 
361
 
363
 
362
$db = array();
364
$db = array();
363
$cats = array();
365
$cats = array();
364
 
366
 
365
// ******** compute the version-sorted list of packages with a single *********
367
// ******** compute the version-sorted list of packages with a single *********
366
// ******** description and category list for each package ********************
368
// ******** description and category list for each package ********************
367
 
369
 
368
// iterate over each svp package
370
// iterate over each svp package
369
foreach ($pkgdb as $pkg => $versions) {
371
foreach ($pkgdb as $pkg => $versions) {
370
 
372
 
371
  // sort filenames by version, highest first
373
  // sort filenames by version, highest first
372
  uksort($versions, "dos_version_compare");
374
  uksort($versions, "dos_version_compare");
373
  $versions = array_reverse($versions, true);
375
  $versions = array_reverse($versions, true);
374
 
376
 
375
  foreach ($versions as $ver => $meta) {
377
  foreach ($versions as $ver => $meta) {
376
    $fname = $meta['fname'];
378
    $fname = $meta['fname'];
377
    $desc = $meta['desc'];
379
    $desc = $meta['desc'];
378
 
380
 
379
    $bsum = file2bsum(realpath($repodir . '/' . $fname));
381
    $bsum = file2bsum(realpath($repodir . '/' . $fname));
380
 
382
 
381
    $meta2['ver'] = strval($ver);
383
    $meta2['ver'] = strval($ver);
382
    $meta2['bsum'] = $bsum;
384
    $meta2['bsum'] = $bsum;
383
 
385
 
384
    if (empty($db[$pkg]['desc'])) $db[$pkg]['desc'] = $desc;
386
    if (empty($db[$pkg]['desc'])) $db[$pkg]['desc'] = $desc;
385
    if (empty($db[$pkg]['cats'])) {
387
    if (empty($db[$pkg]['cats'])) {
386
      $db[$pkg]['cats'] = $meta['cats'];
388
      $db[$pkg]['cats'] = $meta['cats'];
387
      $cats = array_unique(array_merge($cats, $meta['cats']));
389
      $cats = array_unique(array_merge($cats, $meta['cats']));
388
    }
390
    }
389
    $db[$pkg]['versions'][$fname] = $meta2;
391
    $db[$pkg]['versions'][$fname] = $meta2;
390
  }
392
  }
391
 
393
 
392
  $pkgcount++;
394
  $pkgcount++;
393
 
395
 
394
}
396
}
395
 
397
 
396
if ($pkgcount < 100) echo "WARNING: an unexpectedly low number of packages has been found in the repo ({$pkgcount})\n";
398
if ($pkgcount < 100) echo "WARNING: an unexpectedly low number of packages has been found in the repo ({$pkgcount})\n";
397
 
399
 
398
$json_blob = json_encode($db);
400
$json_blob = json_encode($db);
399
if ($json_blob === false) {
401
if ($json_blob === false) {
400
  echo "ERROR: JSON convertion failed! -> ";
402
  echo "ERROR: JSON convertion failed! -> ";
401
  switch (json_last_error()) {
403
  switch (json_last_error()) {
402
    case JSON_ERROR_DEPTH:
404
    case JSON_ERROR_DEPTH:
403
      echo 'maximum stack depth exceeded';
405
      echo 'maximum stack depth exceeded';
404
      break;
406
      break;
405
    case JSON_ERROR_STATE_MISMATCH:
407
    case JSON_ERROR_STATE_MISMATCH:
406
      echo 'underflow of the modes mismatch';
408
      echo 'underflow of the modes mismatch';
407
      break;
409
      break;
408
    case JSON_ERROR_CTRL_CHAR:
410
    case JSON_ERROR_CTRL_CHAR:
409
      echo 'unexpected control character found';
411
      echo 'unexpected control character found';
410
      break;
412
      break;
411
    case JSON_ERROR_UTF8:
413
    case JSON_ERROR_UTF8:
412
      echo 'malformed utf-8 characters';
414
      echo 'malformed utf-8 characters';
413
      break;
415
      break;
414
    default:
416
    default:
415
      echo "unknown error";
417
      echo "unknown error";
416
      break;
418
      break;
417
  }
419
  }
418
  echo "\n";
420
  echo "\n";
419
}
421
}
420
 
422
 
421
file_put_contents($repodir . '/_index.json', $json_blob);
423
file_put_contents($repodir . '/_index.json', $json_blob);
422
 
424
 
423
$cats_json = json_encode($cats);
425
$cats_json = json_encode($cats);
424
file_put_contents($repodir . '/_cats.json', $cats_json);
426
file_put_contents($repodir . '/_cats.json', $cats_json);
425
 
427
 
426
exit(0);
428
exit(0);
427
 
429
 
428
?>
430
?>
429
 
431