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