1: <?php
2: 3: 4: 5: 6: 7:
8:
9: namespace Jlab\Eloglib;
10:
11:
12: use DOMDocument;
13: use DOMXPath;
14: use stdClass;
15:
16: class LogentryUtil
17: {
18:
19: 20: 21: 22:
23: public static $lastServerMsg;
24:
25:
26: 27: 28: 29: 30: 31: 32:
33: public static function saveToFile($filename, Logentry $entry)
34: {
35: if (file_put_contents($filename, $entry->getXML()) === false) {
36: throw new IOException("Failed to write $filename");
37: }
38: }
39:
40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
50: public static function saveToQueue(Logentry $entry, $validate = true)
51: {
52: if ($validate){
53: if (! self::isValidEntry($entry)){
54: throw new InvalidXMLException("Schema validation of the entry fails: \n" . self::validationErrors());
55: }
56: }
57:
58:
59:
60: $filename = self::queuePath() . DIRECTORY_SEPARATOR . self::queueFileName();
61: while (file_exists($filename)) {
62: $filename = self::$queueDir . DIRECTORY_SEPARATOR . self::queueFileName();
63: }
64:
65: if (file_put_contents($filename, $entry->getXML()) === false) {
66: throw new IOException("Failed to save $filename");
67: }
68:
69: return $filename;
70: }
71:
72:
73: public static function queuePath()
74: {
75: return getenv('DEFAULT_UNIX_QUEUE_PATH');
76: }
77:
78: 79: 80: 81: 82:
83: public static function queueFileName()
84: {
85: $pid = posix_getpid();
86: $hostname = trim(`hostname`);
87: $date = date('Ymd');
88: $time = date('His');
89: $name = sprintf("%s_%s_%s_%s_%d.xml", $date, $time, $pid, $hostname, rand(1, 999));
90: return $name;
91: }
92:
93: 94: 95: 96: 97: 98: 99: 100: 101: 102:
103: public static function saveToServer(Logentry $entry)
104: {
105: $xmlFile = self::tmpXMLFile($entry->getXML());
106:
107:
108:
109: $FH = fopen($xmlFile, 'r');
110: $ch = curl_init();
111: curl_setopt($ch, CURLOPT_URL, self::submitUrl($xmlFile));
112: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
113: curl_setopt($ch, CURLOPT_SSLCERT, self::certificateFile());
114: curl_setopt($ch, CURLOPT_INFILE, $FH);
115: curl_setopt($ch, CURLOPT_INFILESIZE, filesize($xmlFile));
116: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
117: curl_setopt($ch, CURLOPT_PUT, true);
118: $result = curl_exec($ch);
119: fclose($FH);
120:
121: if ($result === false) {
122: throw new ServerException('curl failure. Unable to send file.' . curl_error($ch));
123: } else {
124: self::$lastServerMsg = $result;
125: $success = self::extractLognumber($result);
126: unlink($xmlFile);
127: return $success;
128: }
129:
130: }
131:
132: protected static function tmpXMLFile($xml)
133: {
134: $basename = self::queueFileName();
135: $filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $basename;
136:
137: while (file_exists($filename)) {
138: $basename = self::queueFileName();
139: $filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $basename;
140: }
141: if (file_put_contents($filename, $xml) === false) {
142: throw new IOException("Unable to write XML temp file: " . $filename);
143: }
144: return $filename;
145: }
146:
147: protected static function submitUrl($filename)
148: {
149: return getenv('SUBMIT_URL') . '/' . urlencode(basename($filename));
150: }
151:
152: public static function certificateFile()
153: {
154: $filename = getenv('ELOGCERT_FILE');
155: if (self::isSimpleFilename($filename)) {
156: $filename = self::userHome() . DIRECTORY_SEPARATOR . $filename;
157: }
158: return $filename;
159: }
160:
161: 162: 163: 164: 165: 166:
167: public static function isSimpleFilename($filename)
168: {
169: return $filename === basename($filename);
170: }
171:
172: 173: 174: 175: 176: 177: 178:
179: public static function userHome()
180: {
181:
182: $home = getenv('HOME');
183: if (!empty($home)) {
184:
185: $home = rtrim($home, '/');
186: } elseif (!empty($_SERVER['HOMEDRIVE']) && !empty($_SERVER['HOMEPATH'])) {
187:
188: $home = $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH'];
189:
190:
191: $home = rtrim($home, '\\/');
192: }
193: return empty($home) ? null : $home;
194: }
195:
196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217:
218: public static function extractLognumber($text)
219: {
220: $dom = new DOMDocument();
221: if (!$dom->loadXML($text)) {
222: throw new ServerException("Unable to process server response: \n" . $text);
223: }
224:
225: $root = $dom->documentElement->tagName;
226: if ($root == 'Response') {
227: $stat = $dom->documentElement->getAttribute('stat');
228: $xpath = new DOMXpath($dom);
229: if ($stat == 'ok') {
230: return $xpath->query('lognumber')->item(0)->nodeValue;
231: } elseif ($stat == 'fail') {
232: $msg = $xpath->query('msg')->item(0)->nodeValue;
233: throw new ServerException("Error response from Server: \n" . $msg);
234: }
235: }
236: throw new ServerException("Server returned unexpected XML response:\n" . $text);
237: }
238:
239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252:
253: public static function isValidEntry(Logentry $entry, $schema = null)
254: {
255:
256:
257: $filename = tempnam(sys_get_temp_dir(), 'validateXML_');
258: if (file_put_contents($filename, $entry->getXML()) === false) {
259: throw new IOException("Failed to write temp file $filename");
260: }
261:
262: return self::isValidXMLFile($filename, $schema);
263: }
264:
265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278:
279: public static function isValidXMLFile($filename, $schema = null)
280: {
281:
282: if ($schema == null) {
283: $schema = getenv('LOG_ENTRY_SCHEMA_URL');
284: }
285:
286: if (!is_readable($filename)) {
287: throw new IOException("Unable to read $filename for validation");
288: }
289:
290: libxml_use_internal_errors(true);
291:
292: $dom = new DOMDocument();
293: $dom->load($filename, LIBXML_PARSEHUGE);
294:
295: return $dom->schemaValidate($schema);
296: }
297:
298: 299: 300: 301: 302: 303:
304: static public function validationErrors()
305: {
306: $return = '';
307: $errors = libxml_get_errors();
308: foreach ($errors as $error) {
309: $return .= self::getXMLErrorString($error);
310: }
311: libxml_clear_errors();
312: return $return;
313: }
314:
315: 316: 317: 318: 319:
320: static private function getXMLErrorString($error)
321: {
322: $return = '';
323: switch ($error->level) {
324: case LIBXML_ERR_WARNING:
325: $return .= "Warning $error->code: ";
326: break;
327: case LIBXML_ERR_ERROR:
328: $return .= "Error $error->code: ";
329: break;
330: case LIBXML_ERR_FATAL:
331: $return .= "Fatal Error $error->code: ";
332: break;
333: }
334: $return .= trim($error->message) .
335: "\n Line: $error->line" .
336: "\n Column: $error->column";
337: if ($error->file) {
338: $return .= "\n File: $error->file";
339: }
340: return "$return\n\n--------------------------------------------\n\n";
341: }
342:
343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355:
356: public static function getXMLresponse(stdClass $O, $stat = 'ok')
357: {
358: $xw = new xmlWriter();
359: $xw->openMemory();
360: $xw->startDocument();
361: $xw->setIndent(true);
362: $xw->startElement('Response');
363: $xw->writeAttribute('stat', $stat);
364: $xw->writeRaw("\n");
365: foreach (get_object_vars($O) as $n => $var) {
366: $xw->writeElement($n, htmlspecialchars($var));
367: }
368: $xw->endElement();
369: $xw->endDocument();
370: return $xw->outputMemory(true);
371: }
372:
373: protected function hostOS()
374: {
375:
376: }
377:
378: }