param_exists("place_id")) exit("Error: No place id provided.\n"); if(!$this->param_exists("summary")) exit("Error: No summary provided.\n"); if(!$this->param_exists("version")) exit("No version provided.\n"); /******************************************************/ $place = null; foreach($settings->get("places") as $current_place) { if($current_place["key"] == $this->param_get("place_id", null)) { $place = $current_place; break; } } if($place == null) exit("Error: Place id doesn't match.\n"); $new_report = new \stdClass(); $new_report->version = escape4xml($this->param_get("version", "?")); $new_report->summary = escape4xml($this->param_get("summary", "(Unknown error)")); $new_report->details = escape4xml($this->param_get("details", "")); $new_report->stack_trace = $this->get_post_body(); $report_dir = ROOT_DIR . "/{$settings->get("data_dir")}/places/" . slugify($place["name"]); $report_filename = "$report_dir/" . slugify($new_report->summary) . ".xml"; // Create the directory if it doesn't exist already if(!file_exists($report_dir)) mkdir($report_dir, 0750, true); // Save the individual report if(!file_exists($report_filename)) { $writer = new \SBRL\Utilities\SimpleXmlWriter(); // It's started automagically $writer->prettyprint = true; $writer->add_xslt("/theme/stack_traces.xslt"); $writer->open("error_info"); $writer->addtag("project_name", [], $place["name"]); // For aesthetic purposes $writer->addtag("summary", [], $new_report->summary); $writer->open("reports"); $writer->close(); $writer->close(); file_put_contents($report_filename, $writer->render()); } // We have to use a DOMDocument here because SimpleXML mangled the // whitespace in the stack traces $report_xml = new DOMDocument("1.0", "UTF-8"); $report_xml->preserveWhiteSpace = false; $report_xml->formatOutput = true; if(!$report_xml->loadXML(file_get_contents($report_filename), LIBXML_NONET)) exit("Error: Invalid XML generated when creating a new report file.\n"); $report_node = new DOMElement("report"); $report_xml->getElementsByTagName("reports")->item(0)->appendChild($report_node); $report_node->appendChild(new DOMElement("timestamp", date(DATE_ATOM))); $report_node->appendChild(new DOMElement("version", $new_report->version)); $report_node->appendChild(new DOMElement("details", $new_report->details)); $stack_trace_node = new DOMElement("stack_trace"); $report_node->appendChild($stack_trace_node); $stack_trace_node->appendChild($report_xml->createCDATASection($new_report->stack_trace)); // NOTE: When uploading with curl to test this, make sure to use --data-binary and not simply -d, as this mangles the newline characters. file_put_contents($report_filename, $report_xml->saveXML()); // Update the place index $place_index_filename = "$report_dir/index.xml"; if(!file_exists($place_index_filename)) { $writer = new SimpleXmlWriter(); $writer->prettyprint = true; $writer->add_xslt("/theme/error_index.xslt"); $writer->open("errors_index"); $writer->addtag("project_name", [], $place["name"]); $writer->open("error_list"); $writer->close(); $writer->close(); file_put_contents($place_index_filename, $writer->render()); } $index_xml = simplexml_load_file($place_index_filename); $index_entry = null; foreach($index_xml->error_list as $entry) { if($entry->summary->__toString() != $new_report->summary) continue; $index_entry = $entry; break; } if($index_entry == null) { $index_entry = $index_xml->error_list->addChild("error"); $index_entry->summary = $new_report->summary; $index_entry->last_report = date(DATE_ATOM); $index_entry->filename = basename($report_filename); $index_entry->report_count = 0; } $index_entry->report_count = intval($index_entry->report_count) + 1; // This is fine because we don't have to worry about the whitespace in the // stack traces here file_put_contents($place_index_filename, simplexml_asxml_pretty($index_xml)); http_response_code(200); exit("Report submitted successfully!\n"); } }