]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - vendor/justinrainbow/json-schema/bin/validate-json
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / vendor / justinrainbow / json-schema / bin / validate-json
1 #!/usr/bin/env php
2 <?php
3 /**
4  * JSON schema validator
5  *
6  * @author Christian Weiske <christian.weiske@netresearch.de>
7  */
8
9 /**
10  * Dead simple autoloader
11  *
12  * @param string $className Name of class to load
13  *
14  * @return void
15  */
16 function __autoload($className)
17 {
18     $className = ltrim($className, '\\');
19     $fileName  = '';
20     if ($lastNsPos = strrpos($className, '\\')) {
21         $namespace = substr($className, 0, $lastNsPos);
22         $className = substr($className, $lastNsPos + 1);
23         $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
24     }
25     $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
26     if (stream_resolve_include_path($fileName)) {
27         require_once $fileName;
28     }
29 }
30
31 // support running this tool from git checkout
32 if (is_dir(__DIR__ . '/../src/JsonSchema')) {
33     set_include_path(__DIR__ . '/../src' . PATH_SEPARATOR . get_include_path());
34 }
35
36 $arOptions = array();
37 $arArgs = array();
38 array_shift($argv);//script itself
39 foreach ($argv as $arg) {
40     if ($arg{0} == '-') {
41         $arOptions[$arg] = true;
42     } else {
43         $arArgs[] = $arg;
44     }
45 }
46
47 if (count($arArgs) == 0
48     || isset($arOptions['--help']) || isset($arOptions['-h'])
49 ) {
50     echo <<<HLP
51 Validate schema
52 Usage: validate-json data.json
53    or: validate-json data.json schema.json
54
55 Options:
56       --dump-schema     Output full schema and exit
57       --dump-schema-url Output URL of schema
58       --verbose         Show additional output
59       --quiet           Suppress all output
60    -h --help            Show this help
61
62 HLP;
63     exit(1);
64 }
65
66 if (count($arArgs) == 1) {
67     $pathData   = $arArgs[0];
68     $pathSchema = null;
69 } else {
70     $pathData   = $arArgs[0];
71     $pathSchema = getUrlFromPath($arArgs[1]);
72 }
73
74 /**
75  * Show the json parse error that happened last
76  *
77  * @return void
78  */
79 function showJsonError()
80 {
81     $constants = get_defined_constants(true);
82     $json_errors = array();
83     foreach ($constants['json'] as $name => $value) {
84         if (!strncmp($name, 'JSON_ERROR_', 11)) {
85             $json_errors[$value] = $name;
86         }
87     }
88
89     output('JSON parse error: ' . $json_errors[json_last_error()] . "\n");
90 }
91
92 function getUrlFromPath($path)
93 {
94     if (parse_url($path, PHP_URL_SCHEME) !== null) {
95         //already an URL
96         return $path;
97     }
98     if ($path{0} == '/') {
99         //absolute path
100         return 'file://' . $path;
101     }
102
103     //relative path: make absolute
104     return 'file://' . getcwd() . '/' . $path;
105 }
106
107 /**
108  * Take a HTTP header value and split it up into parts.
109  *
110  * @param $headerValue
111  * @return array Key "_value" contains the main value, all others
112  *               as given in the header value
113  */
114 function parseHeaderValue($headerValue)
115 {
116     if (strpos($headerValue, ';') === false) {
117         return array('_value' => $headerValue);
118     }
119
120     $parts = explode(';', $headerValue);
121     $arData = array('_value' => array_shift($parts));
122     foreach ($parts as $part) {
123         list($name, $value) = explode('=', $part);
124         $arData[$name] = trim($value, ' "\'');
125     }
126     return $arData;
127 }
128
129 /**
130  * Send a string to the output stream, but only if --quiet is not enabled
131  *
132  * @param $str A string output
133  */
134 function output($str) {
135     global $arOptions;
136     if (!isset($arOptions['--quiet'])) {
137         echo $str;
138     }
139 }
140
141 $urlData = getUrlFromPath($pathData);
142
143 $context = stream_context_create(
144     array(
145         'http' => array(
146             'header'        => array(
147                 'Accept: */*',
148                 'Connection: Close'
149             ),
150             'max_redirects' => 5
151         )
152     )
153 );
154 $dataString = file_get_contents($pathData, false, $context);
155 if ($dataString == '') {
156     output("Data file is not readable or empty.\n");
157     exit(3);
158 }
159
160 $data = json_decode($dataString);
161 unset($dataString);
162 if ($data === null) {
163     output("Error loading JSON data file\n");
164     showJsonError();
165     exit(5);
166 }
167
168 if ($pathSchema === null) {
169     if (isset($http_response_header)) {
170         array_shift($http_response_header);//HTTP/1.0 line
171         foreach ($http_response_header as $headerLine) {
172             list($hName, $hValue) = explode(':', $headerLine, 2);
173             $hName = strtolower($hName);
174             if ($hName == 'link') {
175                 //Link: <http://example.org/schema#>; rel="describedBy"
176                 $hParts = parseHeaderValue($hValue);
177                 if (isset($hParts['rel']) && $hParts['rel'] == 'describedBy') {
178                     $pathSchema = trim($hParts['_value'], ' <>');
179                 }
180             } else if ($hName == 'content-type') {
181                 //Content-Type: application/my-media-type+json;
182                 //              profile=http://example.org/schema#
183                 $hParts = parseHeaderValue($hValue);
184                 if (isset($hParts['profile'])) {
185                     $pathSchema = $hParts['profile'];
186                 }
187
188             }
189         }
190     }
191     if (is_object($data) && property_exists($data, '$schema')) {
192         $pathSchema = $data->{'$schema'};
193     }
194
195     //autodetect schema
196     if ($pathSchema === null) {
197         output("JSON data must be an object and have a \$schema property.\n");
198         output("You can pass the schema file on the command line as well.\n");
199         output("Schema autodetection failed.\n");
200         exit(6);
201     }
202 }
203 if ($pathSchema{0} == '/') {
204     $pathSchema = 'file://' . $pathSchema;
205 }
206
207 $resolver = new JsonSchema\Uri\UriResolver();
208 $retriever = new JsonSchema\Uri\UriRetriever();
209 try {
210     $urlSchema = $resolver->resolve($pathSchema, $urlData);
211
212     if (isset($arOptions['--dump-schema-url'])) {
213         echo $urlSchema . "\n";
214         exit();
215     }
216 } catch (Exception $e) {
217     output("Error loading JSON schema file\n");
218     output($urlSchema . "\n");
219     output($e->getMessage() . "\n");
220     exit(2);
221 }
222 $refResolver = new JsonSchema\SchemaStorage($retriever, $resolver);
223 $schema = $refResolver->resolveRef($urlSchema);
224
225 if (isset($arOptions['--dump-schema'])) {
226     $options = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
227     echo json_encode($schema, $options) . "\n";
228     exit();
229 }
230
231 try {
232     $validator = new JsonSchema\Validator();
233     $validator->check($data, $schema);
234
235     if ($validator->isValid()) {
236         if(isset($arOptions['--verbose'])) {
237             output("OK. The supplied JSON validates against the schema.\n");
238         }
239     } else {
240         output("JSON does not validate. Violations:\n");
241         foreach ($validator->getErrors() as $error) {
242             output(sprintf("[%s] %s\n", $error['property'], $error['message']));
243         }
244         exit(23);
245     }
246 } catch (Exception $e) {
247     output("JSON does not validate. Error:\n");
248     output($e->getMessage() . "\n");
249     output("Error code: " . $e->getCode() . "\n");
250     exit(24);
251 }