/** * 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 upload_action_process() { $couchDB = false; $harddisk = false; if ($GLOBALS['document_storage_method'] == 0) { $harddisk = true; } if ($GLOBALS['document_storage_method'] == 1) { $couchDB = true; } if ($_POST['process'] != "true") { return; } $doDecryption = false; $encrypted = $_POST['encrypted']; $passphrase = $_POST['passphrase']; if (!$GLOBALS['hide_document_encryption'] && $encrypted && $passphrase) { $doDecryption = true; } if (is_numeric($_POST['category_id'])) { $category_id = $_POST['category_id']; } if (is_numeric($_POST['patient_id'])) { $patient_id = $_POST['patient_id']; } foreach ($_FILES as $file) { $fname = $file['name']; $err = ""; if ($file['error'] > 0 || empty($file['name']) || $file['size'] == 0) { $fname = $file['name']; if (empty($fname)) { $fname = htmlentities("<empty>"); } $error = "Error number: " . $file['error'] . " occured while uploading file named: " . $fname . "\n"; if ($file['size'] == 0) { $error .= "The system does not permit uploading files of with size 0.\n"; } } else { if (!file_exists($this->file_path)) { if (!mkdir($this->file_path, 0700)) { $error .= "The system was unable to create the directory for this upload, '" . $this->file_path . "'.\n"; } } if ($_POST['destination'] != '') { $fname = $_POST['destination']; } $fname = preg_replace("/[^a-zA-Z0-9_.]/", "_", $fname); if (file_exists($this->file_path . $fname)) { $error .= xl('File with same name already exists at location:', '', '', ' ') . $this->file_path . "\n"; $fname = basename($this->_rename_file($this->file_path . $fname)); $file['name'] = $fname; $error .= xl('Current file name was changed to', '', '', ' ') . $fname . "\n"; } if ($doDecryption) { $tmpfile = fopen($file['tmp_name'], "r"); $filetext = fread($tmpfile, $file['size']); $plaintext = $this->decrypt($filetext, $passphrase); fclose($tmpfile); unlink($file['tmp_name']); $tmpfile = fopen($file['tmp_name'], "w+"); fwrite($tmpfile, $plaintext); fclose($tmpfile); $file['size'] = filesize($file['tmp_name']); } $docid = ''; $resp = ''; if ($couchDB == true) { $couch = new CouchDB(); $docname = $_SESSION['authId'] . $patient_id . $encounter . $fname . date("%Y-%m-%d H:i:s"); $docid = $couch->stringToId($docname); $tmpfile = fopen($file['tmp_name'], "rb"); $filetext = fread($tmpfile, $file['size']); fclose($tmpfile); //--------Temporarily writing the file for calculating the hash--------// //-----------Will be removed after calculating the hash value----------// $temp_file = fopen($this->file_path . $fname, "w"); fwrite($temp_file, $filetext); fclose($temp_file); //---------------------------------------------------------------------// $json = json_encode(base64_encode($filetext)); $db = $GLOBALS['couchdb_dbase']; $data = array($db, $docid, $patient_id, $encounter, $file['type'], $json); $resp = $couch->check_saveDOC($data); if (!$resp->id || !$resp->_rev) { $data = array($db, $docid, $patient_id, $encounter); $resp = $couch->retrieve_doc($data); $docid = $resp->_id; $revid = $resp->_rev; } else { $docid = $resp->id; $revid = $resp->rev; } if (!$docid && !$revid) { //if couchdb save failed $error .= "<font color='red'><b>" . xl("The file could not be saved to CouchDB.") . "</b></font>\n"; if ($GLOBALS['couchdb_log'] == 1) { ob_start(); var_dump($resp); $couchError = ob_get_clean(); $log_content = date('Y-m-d H:i:s') . " ==> Uploading document: " . $fname . "\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> Failed to Store document content to CouchDB.\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> Document ID: " . $docid . "\r\n"; $log_content .= date('Y-m-d H:i:s') . " ==> " . print_r($data, 1) . "\r\n"; $log_content .= $couchError; $this->document_upload_download_log($patient_id, $log_content); //log error if any, for testing phase only } } } if ($harddisk == true) { $uploadSuccess = false; if (move_uploaded_file($file['tmp_name'], $this->file_path . $fname)) { $uploadSuccess = true; } else { $error .= xl("The file could not be succesfully stored, this error is usually related to permissions problems on the storage system") . "\n"; } } $this->assign("upload_success", "true"); $d = new Document(); $d->storagemethod = $GLOBALS['document_storage_method']; if ($harddisk == true) { $d->url = "file://" . $this->file_path . $fname; } else { $d->url = $fname; } if ($couchDB == true) { $d->couch_docid = $docid; $d->couch_revid = $revid; } if ($file['type'] == 'text/xml') { $d->mimetype = 'application/xml'; } else { $d->mimetype = $file['type']; } $d->size = $file['size']; $d->owner = $_SESSION['authUserID']; $sha1Hash = sha1_file($this->file_path . $fname); if ($couchDB == true) { //Removing the temporary file which is used to create the hash unlink($this->file_path . $fname); } $d->hash = $sha1Hash; $d->type = $d->type_array['file_url']; $d->set_foreign_id($patient_id); if ($harddisk == true || $couchDB == true && $docid && $revid) { $d->persist(); $d->populate(); } $this->assign("file", $d); if (is_numeric($d->get_id()) && is_numeric($category_id)) { $sql = "REPLACE INTO categories_to_documents set category_id = '" . $category_id . "', document_id = '" . $d->get_id() . "'"; $d->_db->Execute($sql); } if ($GLOBALS['couchdb_log'] == 1 && $log_content != '') { $log_content .= "\r\n\r\n"; $this->document_upload_download_log($patient_id, $log_content); } } } $this->assign("error", nl2br($error)); //$this->_state = false; $_POST['process'] = ""; //return $this->fetch($GLOBALS['template_dir'] . "documents/" . $this->template_mod . "_upload.html"); }