// require_once dirname(__FILE__) . "/../../interface/globals.php"; require_once dirname(__FILE__) . "/../parse_patient_xml.php"; require_once dirname(__FILE__) . "/../classes/Document.class.php"; require_once dirname(__FILE__) . "/../classes/CouchDB.class.php"; if ($_REQUEST["ccr_ajax"] == "yes") { $doc_id = $_REQUEST["document_id"]; $d = new Document($doc_id); $url = $d->get_url(); $storagemethod = $d->get_storagemethod(); $couch_docid = $d->get_couch_docid(); $couch_revid = $d->get_couch_revid(); if ($storagemethod == 1) { $couch = new CouchDB(); $data = array($GLOBALS['couchdb_dbase'], $couch_docid); $resp = $couch->retrieve_doc($data); $content = $resp->data; if ($content == '' && $GLOBALS['couchdb_log'] == 1) { $log_content = date('Y-m-d H:i:s') . " ==> Retrieving document\r\n"; $log_content = date('Y-m-d H:i:s') . " ==> URL: " . $url . "\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> CouchDB Document Id: " . $couch_docid . "\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> CouchDB Revision Id: " . $couch_revid . "\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> Failed to fetch document content from CouchDB.\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> Will try to download file from HardDisk if exists.\r\n\r\n"; $this->document_upload_download_log($d->get_foreign_id(), $log_content); die(xlt("File retrieval from CouchDB failed")); } $content = base64_decode($content); } else { $url = preg_replace("|^(.*)://|", "", $url); $from_all = explode("/", $url);
/** * Create a new document and store its data. * This is a mix of new code and code moved from C_Document.class.php. * * @param string $patient_id Patient pid; if not known then this may be a simple directory name * @param integer $category_id The desired document category ID * @param string $filename Desired filename, may be modified for uniqueness * @param string $mimetype MIME type * @param string &$data The actual data to store (not encoded) * @param string $higher_level_path Optional subdirectory within the local document repository * @param string $path_depth Number of directory levels in $higher_level_path, if specified * @param integer $owner Owner/user/service that is requesting this action * @return string Empty string if success, otherwise error message text */ function createDocument($patient_id, $category_id, $filename, $mimetype, &$data, $higher_level_path = '', $path_depth = 1, $owner = 0) { // The original code used the encounter ID but never set it to anything. // That was probably a mistake, but we reference it here for documentation // and leave it empty. Logically, documents are not tied to encounters. $encounter_id = ''; $this->storagemethod = $GLOBALS['document_storage_method']; $this->mimetype = $mimetype; if ($this->storagemethod == 1) { // Store it using CouchDB. $couch = new CouchDB(); $docname = $_SESSION['authId'] . $filename . $patient_id . $encounter_id . date("%Y-%m-%d H:i:s"); $docid = $couch->stringToId($docname); $json = json_encode(base64_encode($data)); $db = $GLOBALS['couchdb_dbase']; $couchdata = array($db, $docid, $patient_id, $encounter_id, $mimetype, $json); $resp = $couch->check_saveDOC($couchdata); if (!$resp->id || !$resp->_rev) { // Not sure what this is supposed to do. The references to id, rev, // _id and _rev seem pretty weird. $couchdata = array($db, $docid, $patient_id, $encounter_id); $resp = $couch->retrieve_doc($couchdata); $docid = $resp->_id; $revid = $resp->_rev; } else { $docid = $resp->id; $revid = $resp->rev; } if (!$docid && !$revid) { return xl('CouchDB save failed'); } $this->url = $filename; $this->couch_docid = $docid; $this->couch_revid = $revid; } else { // Storing document files locally. $repository = $GLOBALS['oer_config']['documents']['repository']; $higher_level_path = preg_replace("/[^A-Za-z0-9\\/]/", "_", $higher_level_path); if (!empty($higher_level_path) && (is_numeric($patient_id) && $patient_id > 0)) { // Allow higher level directory structure in documents directory and a patient is mapped. $filepath = $repository . $higher_level_path . "/"; } else { if (!empty($higher_level_path)) { // Allow higher level directory structure in documents directory and there is no patient mapping // (will create up to 10000 random directories and increment the path_depth by 1). $filepath = $repository . $higher_level_path . '/' . rand(1, 10000) . '/'; ++$path_depth; } else { if (!is_numeric($patient_id) || !($patient_id > 0)) { // This is the default action except there is no patient mapping (when patient_id is 00 or direct) // (will create up to 10000 random directories and set the path_depth to 2). $filepath = $repository . $patient_id . '/' . rand(1, 10000) . '/'; $path_depth = 2; $patient_id = 0; } else { // This is the default action where the patient is used as one level directory structure in documents directory. $filepath = $repository . $patient_id . '/'; $path_depth = 1; } } } if (!file_exists($filepath)) { if (!mkdir($filepath, 0700, true)) { return xl('Unable to create patient document subdirectory'); } } // Filename modification to force valid characters and uniqueness. $filename = preg_replace("/[^a-zA-Z0-9_.]/", "_", $filename); $fnsuffix = 0; $fn1 = $filename; $fn2 = ''; $fn3 = ''; $dotpos = strrpos($filename, '.'); if ($dotpos !== FALSE) { $fn1 = substr($filename, 0, $dotpos); $fn2 = '.'; $fn3 = substr($filename, $dotpos + 1); } while (file_exists($filepath . $filename)) { if (++$fnsuffix > 10000) { return xl('Failed to compute a unique filename'); } $filename = $fn1 . '_' . $fnsuffix . $fn2 . $fn3; } $this->url = "file://" . $filepath . $filename; if (is_numeric($path_depth)) { // this is for when directory structure is more than one level $this->path_depth = $path_depth; } // Store the file into its proper directory. if (file_put_contents($filepath . $filename, $data) === FALSE) { return xl('Failed to create') . " {$filepath}{$filename}"; } } $this->size = strlen($data); $this->hash = sha1($data); $this->type = $this->type_array['file_url']; $this->owner = $owner ? $owner : $_SESSION['authUserID']; $this->set_foreign_id($patient_id); $this->persist(); $this->populate(); if (is_numeric($this->get_id()) && is_numeric($category_id)) { $sql = "REPLACE INTO categories_to_documents set " . "category_id = '{$category_id}', " . "document_id = '" . $this->get_id() . "'"; $this->_db->Execute($sql); } return ''; }
function get_couch_url($pid, $encounter) { $couch_docid = $this->get_couch_docid(); $couch_url = $this->get_url(); $couch = new CouchDB(); $data = array($GLOBALS['couchdb_dbase'], $couch_docid, $pid, $encounter); $resp = $couch->retrieve_doc($data); $content = $resp->data; $temp_url = $couch_url; $temp_url = $GLOBALS['OE_SITE_DIR'] . '/documents/temp/' . $pid . '_' . $couch_url; $f_CDB = fopen($temp_url, 'w'); fwrite($f_CDB, base64_decode($content)); fclose($f_CDB); return $temp_url; }
function validate_action_process($patient_id = "", $document_id) { $d = new Document($document_id); if ($d->couch_docid && $d->couch_revid) { $file_path = $GLOBALS['OE_SITE_DIR'] . '/documents/temp/'; $url = $file_path . $d->get_url(); $couch = new CouchDB(); $data = array($GLOBALS['couchdb_dbase'], $d->couch_docid); $resp = $couch->retrieve_doc($data); $content = $resp->data; //--------Temporarily writing the file for calculating the hash--------// //-----------Will be removed after calculating the hash value----------// $temp_file = fopen($url, "w"); fwrite($temp_file, base64_decode($content)); fclose($temp_file); } else { $url = $d->get_url(); //strip url of protocol handler $url = preg_replace("|^(.*)://|", "", $url); //change full path to current webroot. this is for documents that may have //been moved from a different filesystem and the full path in the database //is not current. this is also for documents that may of been moved to //different patients. Note that the path_depth is used to see how far down //the path to go. For example, originally the path_depth was always 1, which //only allowed things like documents/1/<file>, but now can have more structured //directories. For example a path_depth of 2 can give documents/encounters/1/<file> // etc. // NOTE that $from_filename and basename($url) are the same thing $from_all = explode("/", $url); $from_filename = array_pop($from_all); $from_pathname_array = array(); for ($i = 0; $i < $d->get_path_depth(); $i++) { $from_pathname_array[] = array_pop($from_all); } $from_pathname_array = array_reverse($from_pathname_array); $from_pathname = implode("/", $from_pathname_array); $temp_url = $GLOBALS['OE_SITE_DIR'] . '/documents/' . $from_pathname . '/' . $from_filename; if (file_exists($temp_url)) { $url = $temp_url; } if ($_POST['process'] != "true") { die("process is '" . $_POST['process'] . "', expected 'true'"); return; } } $d = new Document($document_id); $current_hash = sha1_file($url); $messages = xl('Current Hash') . ": " . $current_hash . "<br>"; $messages .= xl('Stored Hash') . ": " . $d->get_hash() . "<br>"; if ($d->get_hash() == '') { $d->hash = $current_hash; $d->persist(); $d->populate(); $messages .= xl('Hash did not exist for this file. A new hash was generated.'); } else { if ($current_hash != $d->get_hash()) { $messages .= xl('Hash does not match. Data integrity has been compromised.'); } else { $messages .= xl('Document passed integrity check.'); } } $this->_state = false; $this->assign("messages", $messages); if ($d->couch_docid && $d->couch_revid) { //Removing the temporary file which is used to create the hash unlink($GLOBALS['OE_SITE_DIR'] . '/documents/temp/' . $d->get_url()); } return $this->view_action($patient_id, $document_id); }
function change_patient($new_patient_id) { $couch_docid = $this->get_couch_docid(); $couch_revid = $this->get_couch_revid(); // Set the new patient in CouchDB. if ($couch_docid && $couch_revid) { $couch = new CouchDB(); $db = $GLOBALS['couchdb_dbase']; $data = array($db, $couch_docid); $couchresp = $couch->retrieve_doc($data); // CouchDB doesnot support updating a single value in a document. // Have to retrieve the entire document, update the necessary value and save again list($db, $docid, $revid, $patient_id, $encounter, $type, $json) = $data; $data = array($db, $couch_docid, $couch_revid, $new_patient_id, $couchresp->encounter, $couchresp->mimetype, json_encode($couchresp->data)); $resp = $couch->update_doc($data); // Sometimes the response from CouchDB is not available, still it would // have saved in the DB. Hence check one more time. if (!$resp->_id || !$resp->_rev) { $data = array($db, $couch_docid, $new_patient_id, $couchresp->encounter); $resp = $couch->retrieve_doc($data); } if ($resp->_rev == $couch_revid) { return false; } else { $this->set_couch_revid($resp->_rev); } } // Set the new patient in mysql. $this->set_foreign_id($new_patient_id); $this->persist(); // Return true for success. return true; }