$usrID = get_user_id(); $bkm_ID = intval($_POST["bkmk_id"]); if ($bkm_ID && $_POST["save-mode"] == "edit") { if (array_key_exists("tagString", $_POST)) { $tagString = doTagInsertion($bkm_ID); } else { $tagString = NULL; } $updatable = array("bkm_PwdReminder" => array("password-reminder", "passwordReminder"), "bkm_Rating" => array("overall-rating", "rating")); $updates = array(); foreach ($updatable as $colName => $varNames) { if (array_key_exists($varNames[0], $_POST)) { $updates[$colName] = $_POST[$varNames[0]]; } } mysql__update("usrBookmarks", "bkm_ID={$bkm_ID} and bkm_UGrpID={$usrID}", $updates); $res = mysql_query("select " . join(", ", array_keys($updates)) . " from usrBookmarks where bkm_ID={$bkm_ID} and bkm_UGrpID={$usrID}"); if (mysql_num_rows($res) == 1) { $dbVals = mysql_fetch_assoc($res); $hVals = array(); foreach ($dbVals as $colName => $val) { $hVals[$updatable[$colName][1]] = $val; } if ($tagString !== NULL) { $hVals["tagString"] = $tagString; } print "(" . json_format($hVals) . ")"; } else { if ($tagString !== NULL) { print "({tagString: \"" . slash($tagString) . "\"})"; }
/** * register external URL (see saveRecordDetails.php) * $filejson - either url or json string with file data array * * returns ulf_ID */ function register_external($filejson) { $filedata = json_decode($filejson, true); //DEBUG /*****DEBUG****/ //error_log("1.>>>>>".$filedata); /*****DEBUG****/ //error_log("2.>>>>>".print_r($filedata, true)); if (!is_array($filedata)) { //can't parse - assume this is URL - old way $filedata = array(); $url = $filejson; //1. get url, source and type $acfg = explode('|', $url); $filedata['remoteURL'] = $acfg[0]; $filedata['ext'] = NULL; if (count($acfg) < 3) { $oType = detectSourceAndType($url); $filedata['remoteSource'] = $oType[0]; $filedata['mediaType'] = $oType[1]; $filedata['ext'] = $oType[2]; } else { $filedata['remoteSource'] = $acfg[1]; $filedata['mediaType'] = $acfg[2]; if (count($acfg) == 4) { $filedata['ext'] = $acfg[3]; } } } if (@$filedata['ext'] == null && $filedata['mediaType'] == "xml") { $filedata['ext'] = "xml"; } //*****DEBUG****/// error_log("reg remote file data ".print_r($filedata,true)); $fileparameters = @$filedata['params'] ? $filedata['params'] : "mediatype=" . $filedata['mediaType']; if (@$filedata['remoteSource'] && $filedata['remoteSource'] != 'heurist') { // && $filedata['remoteSource']!='generic'){ $fileparameters = $fileparameters . "|source=" . $filedata['remoteSource']; } //if id is defined if (array_key_exists('id', $filedata) && intval($filedata['id']) > 0) { //update $file_id = $filedata['id']; //ignore registration for already uploaded file if (array_key_exists('remoteSource', $filedata) && $filedata['remoteSource'] != 'heurist') { mysql__update('recUploadedFiles', 'ulf_ID=' . $file_id, array('ulf_Modified' => date('Y-m-d H:i:s'), 'ulf_MimeExt ' => $filedata['ext'], 'ulf_ExternalFileReference' => $filedata['remoteURL'], 'ulf_Parameters' => $fileparameters)); } } else { if (!array_key_exists('remoteURL', $filedata) || $filedata['remoteURL'] == null || $filedata['remoteURL'] == "") { return null; } //2. find duplication (the same url) if (array_key_exists('remoteSource', $filedata) && $filedata['remoteSource'] != 'heurist') { $res = mysql_query('select ulf_ID from recUploadedFiles ' . 'where ulf_ExternalFileReference = "' . addslashes($filedata['remoteURL']) . '"'); if (mysql_num_rows($res) == 1) { $row = mysql_fetch_assoc($res); $file_id = $row['ulf_ID']; mysql__update('recUploadedFiles', 'ulf_ID=' . $file_id, array('ulf_Modified' => date('Y-m-d H:i:s'), 'ulf_MimeExt ' => $filedata['ext'], 'ulf_Parameters' => $fileparameters)); return $file_id; } } //3. save into recUploadedFiles $res = mysql__insert('recUploadedFiles', array('ulf_OrigFileName' => '_remote', 'ulf_UploaderUGrpID' => get_user_id(), 'ulf_Added' => date('Y-m-d H:i:s'), 'ulf_MimeExt ' => array_key_exists('ext', $filedata) ? $filedata['ext'] : NULL, 'ulf_FileSizeKB' => 0, 'ulf_Description' => NULL, 'ulf_ExternalFileReference' => array_key_exists('remoteURL', $filedata) ? $filedata['remoteURL'] : NULL, 'ulf_Parameters' => $fileparameters)); if (!$res) { /*****DEBUG****/ //error_log("ERROR Insert record: ".mysql_error()); return null; //"Error registration remote source $url into database"; } $file_id = mysql_insert_id(); mysql_query('update recUploadedFiles set ulf_ObfuscatedFileID = "' . addslashes(sha1($file_id . '.' . rand())) . '" where ulf_ID = ' . $file_id); } //4. returns ulf_ID return $file_id; }
function do_file_update(&$file, $type, $condition, $new_filename) { global $FILES, $MAINTABLES; global $MYSQL_ERRORS; $updates = array(); if (!@$FILES[$type]) { fatal("{$type} objects aren't associated with a file upload"); } if (!@$file['filename']) { fatal("non-file passed through to do_file_update"); } if (@$FILES[$type]['name']) { $updates[$FILES[$type]['name']] = $file['filename']; } if (@$FILES[$type]['size']) { $updates[$FILES[$type]['size']] = $file['size']; } if (@$FILES[$type]['type']) { $updates[$FILES[$type]['type']] = $file['filetype']; } $updates[$FILES[$type]['path']] = $new_filename; if (!move_uploaded_file($file['localpath'], HEURIST_FILESTORE_DIR . '/' . $new_filename)) { fatal("desperate failure while handling uploaded file"); } if (!mysql__update($MAINTABLES[$type], $condition, $updates)) { array_push($MYSQL_ERRORS, mysql_error()); } }
function saveWoot($args) { if (!is_logged_in()) { return array("success" => false, "errorType" => "no logged-in user"); } mysql_connection_overwrite(DATABASE); $wootId = intval(@$args["id"]); $wootTitle = mysql_real_escape_string(@$args["title"]); mysql_query("start transaction"); if (!$wootId || $wootId === "new") { /* This is a new WOOT that hasn't been saved yet */ if (!$wootTitle) { return array("success" => false, "errorType" => "missing title"); } mysql__insert(WOOT_TABLE, array("woot_Title" => $wootTitle, "woot_Created" => array("now()"), "woot_Modified" => array("now()"), "woot_Version" => 0, "woot_CreatorID" => get_user_id())); $wootId = mysql_insert_id(); if (!$wootId) { return array("success" => false, "errorType" => "a woot with the given title already exists"); } $woot = mysql_fetch_assoc(mysql_query("select * from " . WOOT_TABLE . " where woot_ID={$wootId}")); $woot["permissions"] = $args["permissions"]; $result = insertWootPermissions($wootId, $woot); if ($result["success"] != true) { return $result; } } else { /* We are saving the WOOT -- get a new version number, commit, and then do chunk-wise operations. * Other people can operate on a separate version at the same time. */ if (!hasWootWritePermission($wootId)) { return array("success" => false, "errorType" => "woot doesn't exist, or insufficient permissions on woot"); } mysql_query("update " . WOOT_TABLE . " set woot_Version=woot_Version+1 where woot_ID={$wootId}"); } $res = mysql_query("select * from " . WOOT_TABLE . " where woot_ID={$wootId}"); mysql_query("commit and chain"); $woot = mysql_fetch_assoc($res); $version = intval($woot["woot_Version"]); $chunkIds = getReadableChunks($wootId, true); $res = mysql_query("select * from " . CHUNK_TABLE . "\n\t\t\t\t\t\t\t where chunk_WootID={$wootId} and chunk_IsLatest and !chunk_Deleted and chunk_ID in (" . join(",", $chunkIds) . ")\n\t\t\t\t\t\t order by chunk_DisplayOrder"); $existingVisibleChunks = array(); while ($chunk = @mysql_fetch_assoc($res)) { /* The @ takes care of the possibility that there are no chunks in this woot */ $existingVisibleChunks[$chunk["chunk_InsertOrder"]] = $chunk; } $incomingChunks = $args["chunks"]; // Get the current chunk ordering (including the chunks the current user can't actually see) $existingChunkOrder = mysql__select_array(CHUNK_TABLE, "chunk_InsertOrder", "chunk_WootID={$wootId} and chunk_IsLatest and ! chunk_Deleted order by chunk_DisplayOrder"); reset($existingChunkOrder); // Check that the incoming chunks are in the same order as the existing chunks, otherwise raise an error if (count($existingChunkOrder)) { foreach ($incomingChunks as $chunk) { if (!@$chunk["number"]) { continue; } // new chunk, doesn't have an ordering yet while (current($existingChunkOrder) != $chunk["number"]) { if (next($existingChunkOrder) === FALSE) { // Ran out of existing chunks // The incoming chunk is out of order (you're out of order, the whole court's out of order) return array("success" => false, "errorType" => "invalid chunk ordering", "chunkNonce" => $chunk["nonce"]); } } } } $chunkNonceToNumber = array(); $newChunks = array(NULL => array()); $newChunkCount = 0; $firstExistingChunk = NULL; $lastExistingChunk = NULL; foreach ($incomingChunks as $chunk) { $prevChunkId = NULL; if (@$chunk["number"]) { // If the incoming chunk has a number which doesn't correspond to an existing chunk, // then the user has had permissions pulled out from under them (or they're playing funny buggers) // Either way, raise an error if (!@$existingVisibleChunks[$chunk["number"]]) { return array("success" => false, "errorType" => "chunk permissions have changed", "chunkNonce" => $chunk["nonce"]); } $chunkNumber = intval($chunk["number"]); // Keep track of the position of this (existing) chunk. // Any new chunks that occur before the next (existing) chunk will be stored in $newChunks[$lastExistingChunk] if (!$firstExistingChunk) { $firstExistingChunk = $chunkNumber; } $lastExistingChunk = $chunkNumber; $newChunks[$lastExistingChunk] = array(); if (!@$chunk["unmodified"]) { // Chunk exists, and is reported as modified. Make a new version of it. $res = mysql_query("select chunk_ID, chunk_DisplayOrder, chunk_OwnerID from " . CHUNK_TABLE . " where chunk_WootID={$wootId} and chunk_InsertOrder={$chunkNumber} and chunk_IsLatest"); if (mysql_num_rows($res) != 1) { /* should do something ... do we care? */ } $prevChunk = mysql_fetch_assoc($res); $prevChunkId = $prevChunk["chunk_ID"]; $chunkOrder = $prevChunk["chunk_DisplayOrder"]; $chunkOwner = $prevChunk["chunk_OwnerID"]; mysql__update(CHUNK_TABLE, "chunk_WootID={$wootId} and chunk_InsertOrder={$chunkNumber}", array("chunk_IsLatest" => 0)); } else { // Chunk exists, but is not modified. Nothing more to do. continue; } } else { $res = mysql_query("select max(chunk_InsertOrder) from " . CHUNK_TABLE . " where chunk_WootID={$wootId}"); $chunkNumber = @mysql_fetch_row($res); $chunkNumber = intval(@$chunkNumber[0]) + 1; $chunkOrder = 0; // chunk order will be overridden anyway since there is a new chunk to take care of $chunkOwner = get_user_id(); array_push($newChunks[$lastExistingChunk], $chunkNumber); ++$newChunkCount; } $chunkDeleted = preg_match('/^\\s*$/', $chunk["text"]); mysql__insert(CHUNK_TABLE, array("chunk_WootID" => $wootId, "chunk_InsertOrder" => $chunkNumber, "chunk_Version" => $version, "chunk_Text" => $chunk["text"], "chunk_IsLatest" => 1, "chunk_DisplayOrder" => $chunkOrder, "chunk_Modified" => array("now()"), "chunk_OwnerID" => $chunkOwner, "chunk_EditorID" => get_user_id(), "chunk_Deleted" => $chunkDeleted)); $chunkId = mysql_insert_id(); if (!$chunkDeleted) { if ($chunkOwner == get_user_id() || is_admin()) { // only the owner (or an admin) can change the permissions $result = insertPermissions($chunkId, $chunk, $woot["woot_CreatorID"]); if ($result["success"] != true) { return $result; } } else { // copy the permissions from the previous version of the chunk mysql_query("insert into " . PERMISSION_TABLE . "\n\t\t\t\t\t\t\t\t (wprm_ChunkID, wprm_UGrpID, wprm_GroupID, wprm_Type, wprm_CreatorID, wprm_Created)\n\t\t\t\t\t\t select distinct {$chunkId}, wprm_UGrpID, wprm_GroupID, wprm_Type, wprm_CreatorID, wprm_Created\n\t\t\t\t\t\t\t from " . PERMISSION_TABLE . " where wprm_ChunkID={$prevChunkId}"); } if (@$chunk["nonce"]) { // if the client hasn't specified a nonce they're obviously not interested in the resulting chunk number $chunkNonceToNumber[$chunk["nonce"]] = $chunkNumber; } } else { if ($chunk["nonce"]) { $chunkNonceToNumber[$chunk["nonce"]] = NULL; // blast away the existing number for this chunk } } } if ($newChunkCount) { // New chunks have been inserted. // Make a merged list of existing chunks and newly inserted chunks, then update their ordering $allChunks = array(); foreach ($existingChunkOrder as $existingChunkNumber) { // Consider chunks (A, B*, C*, D, E*) where B*, C* and E* are new chunks, and A and D are existing chunks. // In the merged list, B* and C* will directly follow A, and E* will directly follow D. // So, given existingChunkOrder (X, A, Y, D, Z) and chunkNonceToNumber (A, B*, C*, D, E*), // allChunks becomes (X, A, B*, C*, Y, D, E*, Z) if ($existingChunkNumber == $firstExistingChunk && count($newChunks[NULL])) { // This is the first chunk that the user can see, and there are new chunks to add before it. $allChunks = array_merge($allChunks, $newChunks[NULL]); } array_push($allChunks, $existingChunkNumber); if (count(@$newChunks[$existingChunkNumber])) { // There are new chunks to add directly after this chunk $allChunks = array_merge($allChunks, $newChunks[$existingChunkNumber]); } } if (!$firstExistingChunk && count($newChunks[NULL])) { // Okay, there were no existing chunks that the user could see ... add any new chunks at the end $allChunks = array_merge($allChunks, $newChunks[NULL]); } for ($i = 0; $i < count($allChunks); ++$i) { $order = $i + 1; $chunkNumber = $allChunks[$i]; mysql_query("update " . CHUNK_TABLE . " set chunk_DisplayOrder={$order}\n\t\t\t\t\t\t\t where chunk_WootID={$wootId} and chunk_InsertOrder={$chunkNumber} and chunk_IsLatest"); } } mysql_query("commit"); return array("success" => true, "id" => $wootId, "version" => $version, "chunks" => $chunkNonceToNumber); }
/** * Main method that parses POST and update details for given record ID * * @param int $recID */ function updateRecord($recID, $rtyID = null) { // Update the given record. // This is non-trivial: so that the versioning stuff (achive_*) works properly // we need to separate this into updates, inserts and deletes. // We get the currect record details and compare them against the post // if the details id is in the post[dtyID][dtlID] then compare the values $recID = intval($recID); // Check that the user has permissions to edit it. $res = mysql_query("select * from Records" . " left join sysUsrGrpLinks on ugl_GroupID=rec_OwnerUGrpID" . " left join defRecTypes on rty_ID=rec_RecTypeID" . " where rec_ID={$recID} and (! rec_OwnerUGrpID or rec_OwnerUGrpID=" . get_user_id() . " or ugl_UserID=" . get_user_id() . ")"); if (mysql_num_rows($res) == 0) { $res = mysql_query("select grp.ugr_Name from Records, " . USERS_DATABASE . ".sysUGrps grp where rec_ID={$recID} and grp.ugr_ID=rec_OwnerUGrpID"); $grpName = mysql_fetch_row($res); $grpName = $grpName[0]; print '({ error: "\\nSorry - you can\'t edit this record.\\nYou aren\'t in the ' . slash($grpName) . ' workgroup" })'; return; } $record = mysql_fetch_assoc($res); /*****DEBUG****/ error_log("save record dtls POST " . print_r($_POST, true)); // Upload any files submitted ... (doesn't have to take place right now, but may as well) uploadFiles(); //Artem: it does not work here - since we uploaded files at once // Get the existing records details and compare them to the incoming data $recDetails = getRecordDetails($recID); // find UPDATES - everything that is in current record and has a post value is treated as an update $recDetailUpdates = array(); /*****DEBUG****/ //error_log("save record dtls ".print_r($recDetails,true)); foreach ($recDetails as $dtyID => $dtlIDs) { $eltName = "type:" . $dtyID; if (!(@$_POST[$eltName] && is_array($_POST[$eltName]))) { // element wasn't in POST: ignore it -this could be a non-rectype detail unset($recDetails[$dtyID]); // remove from details so it's not deleted continue; } if (count($_POST[$eltName]) == 0) { // element was in POST but without content: values have been deleted client-side (need to be deleted in DB so leave POST) continue; } $bdInputHandler = getInputHandlerForType($dtyID); //returns the particular handler (processor) for given field type foreach ($dtlIDs as $dtlID => $val) { /*****DEBUG****/ //error_log(" in saveRecord details loop $dtyID, $dtlID, ".print_r($val,true)); $eltID = "bd:" . $dtlID; $val = @$_POST[$eltName][$eltID]; if (!$bdInputHandler->inputOK($val, $dtyID, $rtyID)) { /*****DEBUG****/ //error_log(" in saveRecord update details value check error $dtyID, $dtlID, ".print_r($val,true)); continue; // faulty input ... ignore } $toadd = $bdInputHandler->convertPostToMysql($val); /*****DEBUG****/ //error_log(" in saveRecord update details value converted from $val to $toadd"); if ($toadd == null) { continue; } $recDetailUpdates[$dtlID] = $toadd; $recDetailUpdates[$dtlID]["dtl_DetailTypeID"] = $dtyID; /* @TODO Since this function is utilized in (email)import we need to add verification of values according to detail type at the first for terms (enumeration field type) */ unset($_POST[$eltName][$eltID]); // remove data from post submission if (count($_POST[$eltName]) == 0) { // if nothing left in post dtyID then remove it also unset($_POST[$eltName]); } unset($recDetails[$dtyID][$dtlID]); // remove data from local reflection of the database } } /*****DEBUG****/ //error_log("save record dtls POST after updates removed ".print_r($_POST,true)); /*****DEBUG****/ //error_log("save record dtls after updates removed ".print_r($recDetails,true)); // find DELETES // Anything left in recDetails now represents recDetails rows that need to be deleted $bibDetailDeletes = array(); foreach ($recDetails as $dtyID => $dtlIDs) { foreach ($dtlIDs as $dtlID => $val) { array_push($bibDetailDeletes, $dtlID); } } // find INSERTS // Try to insert anything left in POST as new recDetails rows $bibDetailInserts = array(); /*****DEBUG****/ error_log(" in saveRecord checking for inserts _POST =" . print_r($_POST, true)); foreach ($_POST as $eltName => $bds) { // if not properly formatted or empty or an empty array then skip it if (!preg_match("/^type:\\d+\$/", $eltName) || !$_POST[$eltName] || count($_POST[$eltName]) == 0) { continue; } $dtyID = substr($eltName, 5); $bdInputHandler = getInputHandlerForType($dtyID); foreach ($bds as $eltID => $val) { if (!$bdInputHandler->inputOK($val, $dtyID, $rtyID)) { /*****DEBUG****/ //error_log(" in saveRecord insert details value check error for $eltName, $eltID, ".print_r($val,true)); continue; // faulty input ... ignore } $newBibDetail = $bdInputHandler->convertPostToMysql($val); $newBibDetail["dtl_DetailTypeID"] = $dtyID; $newBibDetail["dtl_RecID"] = $recID; /*****DEBUG****/ //error_log("new detail ".print_r($newBibDetail,true)); array_push($bibDetailInserts, $newBibDetail); unset($_POST[$eltName][$eltID]); // remove data from post submission } } // Anything left in POST now is stuff that we have no intention of inserting ... ignore it // We now have: // - $recDetailUpdates: an assoc. array of dtl_ID => column values to be updated in recDetails // - $bibDetailInserts: an array of column values to be inserted into recDetails // - $bibDetailDeletes: an array of dtl_ID values corresponding to rows to be deleted from recDetails // Commence versioning ... mysql_query("start transaction"); $recUpdates = array("rec_Modified" => array("now()"), "rec_FlagTemporary" => 0); $recUpdates["rec_ScratchPad"] = $_POST["notes"]; if (intval(@$_POST["rectype"])) { $recUpdates["rec_RecTypeID"] = intval($_POST["rectype"]); } if (array_key_exists("rec_url", $_POST)) { $recUpdates["rec_URL"] = $_POST["rec_url"]; } $owner = $record['rec_OwnerUGrpID']; if (is_admin() || is_admin('group', $owner) || $owner == get_user_id()) { // must be grpAdmin or record owner to changes ownership or visibility if (array_key_exists("rec_owner", $_POST)) { $recUpdates["rec_OwnerUGrpID"] = $_POST["rec_owner"]; } if (array_key_exists("rec_visibility", $_POST)) { $recUpdates["rec_NonOwnerVisibility"] = $_POST["rec_visibility"]; } else { if ($record['rec_NonOwnerVisibility'] == 'public' && HEURIST_PUBLIC_TO_PENDING) { $recUpdates["rec_NonOwnerVisibility"] = 'pending'; } } } /*****DEBUG****/ error_log(" in saveRecord update recUpdates = " . print_r($recUpdates, true)); mysql__update("Records", "rec_ID={$recID}", $recUpdates); $biblioUpdated = mysql_affected_rows() > 0 ? true : false; if (mysql_error()) { error_log("error rec update" . mysql_error()); } $updatedRowCount = 0; foreach ($recDetailUpdates as $bdID => $vals) { /*****DEBUG****/ error_log(" in saveRecord update details dtl_ID = {$bdID} value =" . print_r($vals, true)); mysql__update("recDetails", "dtl_ID={$bdID} and dtl_RecID={$recID}", $vals); if (mysql_affected_rows() > 0) { ++$updatedRowCount; } } if (mysql_error()) { error_log("error detail updates" . mysql_error()); } $insertedRowCount = 0; foreach ($bibDetailInserts as $vals) { /*****DEBUG****/ error_log(" in saveRecord insert details detail =" . print_r($vals, true)); mysql__insert("recDetails", $vals); if (mysql_affected_rows() > 0) { ++$insertedRowCount; } } if (mysql_error()) { error_log("error detail inserts" . mysql_error()); } $deletedRowCount = 0; if ($bibDetailDeletes) { /*****DEBUG****/ error_log(" in saveRecord delete details " . print_r($bibDetailDeletes, true)); mysql_query("delete from recDetails where dtl_ID in (" . join($bibDetailDeletes, ",") . ") and dtl_RecID={$recID}"); if (mysql_affected_rows() > 0) { $deletedRowCount = mysql_affected_rows(); } } if (mysql_error()) { error_log("error detail deletes" . mysql_error()); } // eliminate any duplicated lines $notesIn = explode("\n", str_replace("\r", "", $_POST["notes"])); $notesOut = ""; $notesMap = array(); for ($i = 0; $i < count($notesIn); ++$i) { if (!@$notesMap[$notesIn[$i]] || !$notesIn[$i]) { // preserve blank lines $notesOut .= $notesIn[$i] . "\n"; $notesMap[$notesIn[$i]] = true; } } $_POST["notes"] = preg_replace("/\n\n+/", "\n", $notesOut); if ($updatedRowCount > 0 || $insertedRowCount > 0 || $deletedRowCount > 0 || $biblioUpdated) { /* something changed: update the records title and commit all changes */ $title_check = check_title_mask2($record["rty_TitleMask"], $record["rec_RecTypeID"], true); if ($title_check != '') { $new_title = "Please go to Designer View > Essentials > Record types/fields and edit the title mask for this record type"; } else { $new_title = fill_title_mask($record["rty_TitleMask"], $record["rec_ID"], $record["rec_RecTypeID"]); } mysql_query("update Records\n set rec_Title = '" . addslashes($new_title) . "'\n where rec_ID = {$recID}"); mysql_query("commit"); // Update memcached's copy of record (if it is cached) updateCachedRecord($recID); return true; } else { /* nothing changed: rollback the transaction so we don't get false versioning */ mysql_query("rollback"); return false; } }
function handleComments($recordID, $removals, $modifications, $additions) { // removals are encoded as just the comments ID# ... easy. if ($removals) { $removals = array_map("intval", $removals); mysql_query("update recThreadedComments set cmt_Deleted=1\n where cmt_OwnerUGrpID=" . get_user_id() . " and cmt_RecID={$recordID} and cmt_ID in (" . join(",", $removals) . ")"); } // modifications have the values // .id, .parentComment, .text foreach ($modifications as $modification) { // note that parentComment (of course) cannot be modified mysql__update("recThreadedComments", "cmt_ID=" . intval($modification["id"]) . " and cmt_OwnerUGrpID=" . get_user_id(), array("cmt_Text" => $modification["text"], "cmt_Modified" => date('Y-m-d H:i:s'))); } // additions are the same as modifications, except that the COMMENT-ID is blank (of course!) $newIDs = array(); foreach ($additions as $addition) { $parentID = intval($addition["parentComment"]); // do a sanity check first: does this reply make sense? $parentTest = $parentID ? "cmt_ID={$parentID}" : "cmt_ID is null"; if (!mysql__select_array("Records left join recThreadedComments on rec_ID=cmt_RecID and {$parentTest}", "rec_ID", "rec_ID={$recordID} and {$parentTest}")) { array_push($newIDs, array("error" => "invalid parent comments")); continue; } if (!$parentID || intval($parentID) === 0) { $parentID = null; } mysql__insert("recThreadedComments", array("cmt_Text" => $addition["text"], "cmt_Added" => date('Y-m-d H:i:s'), "cmt_OwnerUGrpID" => get_user_id(), "cmt_ParentCmtID" => $parentID, "cmt_RecID" => $recordID)); array_push($newIDs, array("id" => mysql_insert_id())); } return $newIDs; }
<div id="page-inner" style="overflow:auto;padding-left: 20px;"> <div>This function removes invalid characters in the data fields in the database records<br /> <hr /></div> <table> <?php mysql_connection_overwrite(DATABASE); $prevInvalidRecId = 0; foreach ($textDetails as $textDetail) { if (!check($textDetail['dtl_Value'])) { if ($prevInvalidRecId < $textDetail['dtl_RecID']) { print "<tr><td><a target=_blank href='" . HEURIST_BASE_URL . "records/edit/editRecord.html?recID=" . $textDetail['dtl_RecID'] . "&db=" . HEURIST_DBNAME . "'> " . $textDetail['dtl_RecID'] . "</a></td></tr>\n"; $prevInvalidRecId = $textDetail['dtl_RecID']; mysql__update("Records", "rec_ID=" . $textDetail['dtl_RecID'], array("rec_Modified" => $now)); } print "<tr><td><pre>" . "Invalid characters found in " . $textDetail['dty_Name'] . " field :</pre></td></tr>\n"; $newText = str_replace($invalidChars, $replacements, $textDetail['dtl_Value']); mysql__update("recDetails", "dtl_ID=" . $textDetail['dtl_ID'], array("dtl_Value" => $newText)); if (mysql_error()) { print "<tr><td><pre>" . "Error " . mysql_error() . "while updating to : " . htmlspecialchars($newText) . "</pre></td></tr>\n"; } else { print "<tr><td><pre>" . "Updated to : " . htmlspecialchars($newText) . "</pre></td></tr>\n"; } } } function check($text) { global $invalidChars; foreach ($invalidChars as $charCode) { if (strpos($text, $charCode)) { error_log("found invalid char "); return false; }
} mysql_connection_overwrite(DATABASE); header("Content-type: text/javascript"); $cmt_id = intval(@$_POST["cmt_ID"]); $rec_id = intval(@$_POST["recID"]); $owner = intval(@$_POST["owner"]); if ($cmt_id) { // UPDATE COMMENT $updates = array("cmt_Modified" => array("now()")); if (@$_POST["text"]) { $updates["cmt_Text"] = $_POST["text"]; } if (array_key_exists("delete", $_POST)) { $updates["cmt_Deleted"] = true; } mysql__update("recThreadedComments", "cmt_ID={$cmt_id} and cmt_OwnerUgrpID=" . get_user_id(), $updates); if (mysql_error()) { $error = mysql_error(); } $res = mysql_query("select * from recThreadedComments left join " . USERS_DATABASE . ".sysUGrps usr on cmt_OwnerUgrpID=usr.ugr_ID where cmt_ID={$cmt_id} and ! cmt_Deleted"); $cmt = mysql_fetch_assoc($res); } else { if ($rec_id) { // ADD NEW COMMENT TO RECORD $inserts = array("cmt_Text" => $_POST["text"], "cmt_Added" => array("now()"), "cmt_OwnerUgrpID" => get_user_id(), "cmt_RecID" => $rec_id); if ($owner) { $inserts["cmt_ParentCmtID"] = $owner; } mysql__insert("recThreadedComments", $inserts); if (mysql_error()) { $error = mysql_error();
if (executeScript($dir . $filename)) { $src_min++; print "<p>Upgraded to " . $src_maj . "." . $src_min . ".0</p>"; } else { $upgrade_success = false; } } else { print "<p style='font-weight:bold'>Cannot find the database upgrade script '" . $filename . "'. Please contact Heurist support</p>"; $upgrade_success = false; break; } } if ($src_min > $keep_minver) { //update database mysql_connection_overwrite(DATABASE); mysql__update("sysIdentification", "1", array("sys_dbSubVersion" => $src_min, "sys_dbSubSubVersion" => "0")); print "<br>"; } if ($upgrade_success) { print "<p>Upgrade was successeful. <a href='" . HEURIST_BASE_URL . "?db=" . HEURIST_DBNAME . "'>Return to main page</a></p>"; } } else { ?> <p>Your database <b> <?php echo HEURIST_DBNAME; ?> </b> currently uses database format version <b><?php echo HEURIST_DBVERSION; ?> </b>
/** * save_search : save the current search criteria as a saved search in the saved searches table * * @param mixed $data */ function save_search($data) { $result = array(); $wg = intval(@$data['svs_UGrpID']); $sID = @$data['svs_ID']; //$publish = $data['publish']; $label = @$data['svs_Name']; $now = date('Y-m-d'); $cmb = array('svs_Name' => $label, 'svs_Query' => @$data['svs_Query'], 'svs_UGrpID' => $wg > 0 ? $wg : get_user_id(), 'svs_Added' => $now, 'svs_Modified' => $now); /* overwrites saved search with same name $res = mysql_query('select svs_ID, svs_UGrpID from usrSavedSearches where svs_Name="'.slash($_REQUEST['svs_Name']).'"'. ' and svs_UGrpID='.$cmb['svs_UGrpID']); $row = mysql_fetch_row($res);*/ mysql_connection_overwrite(DATABASE); if ($sID) { /*$row || if ($row ) { $ss = intval($row[0]); }*/ mysql__update('usrSavedSearches', 'svs_ID=' . $sID, $cmb); } else { mysql__insert('usrSavedSearches', $cmb); $sID = mysql_insert_id(); } if (mysql_error()) { $result['problem'] = 'MySQL error: ' . addslashes(mysql_error()) . ' : search not saved'; } else { // execute function in calling context insertSavedSearch(ssName, ssQuery, wg, ssID) $result['execute'] = array('insertSavedSearch', $data['svs_Name'], $data['svs_Query'], $wg, $sID); //$onload = "location.replace('actionHandler.php?db=".HEURIST_DBNAME."'); top.HEURIST.search.insertSavedSearch('".slash($data['svs_Name'])."', '".slash($data['svs_Query'])."', ".$wg.", ".$sID.");"; /*if ($publish) { $onload .= " top.location.href = top.location.href + (top.location.href.match(/\?/) ? '&' : '?') + 'pub=1&label=".$label."&sid=".$ss."'+(top.location.href.match(/db=/) ? '' : '&db=".HEURIST_DBNAME."');"; }else{ $onload .= ' top.location.href = top.location.href + (top.location.href.match(/\?/) ? \'&\' : \'?\') + \'label='.$label.'&sid='.$ss.'\'+(top.location.href.match(/db=/) ? \'\' : \'&db='.HEURIST_DBNAME.'\');'; }*/ } return $result; }
function do_fix_dupe() { $master_rec_id = $_SESSION['master_rec_id']; $master_details = $_SESSION['master_details']; unset($_SESSION['master_details']); //clear master_details so we don't re-enter this code unset($_SESSION['master_rec_id']); $_SESSION['finished_merge'] = 1; // set state variable for next loop $dup_rec_ids = array(); if (in_array($master_rec_id, explode(',', $_REQUEST['bib_ids']))) { $dup_rec_ids = array_diff(explode(',', $_REQUEST['bib_ids']), array($master_rec_id)); } $dup_rec_list = '(' . join(',', $dup_rec_ids) . ')'; $add_dt_ids = array(); // array of detail ids to insert for the master record grouped by detail type is $update_dt_ids = array(); // array of detail ids to get value for updating the master record $keep_dt_ids = array(); // array of master record repeatable detail ids to keep grouped by detail type id- used to find master details to remove //parse form data foreach ($_REQUEST as $key => $value) { preg_match('/(add|update|keep)(\\d+)/', $key, $matches); if (!$matches) { continue; } switch (strtolower($matches[1])) { case 'add': $add_dt_ids[$matches[2]] = $value; break; case 'update': if ($value != "master") { $update_dt_ids[$matches[2]] = $value; } break; case 'keep': $keep_dt_ids[$matches[2]] = $value; break; } } // mysql_connection_overwrite("`heuristdb-nyirti`"); //for debug mysql_connection_overwrite(DATABASE); // mysql_query('set @suppress_update_trigger:=1'); // shut off update triggers to let us munge the records with out worrying about the archive. // set modified on master so the changes will stick aslo update url if there is one. $now = date('Y-m-d H:i:s'); $pairs = @$_REQUEST['URL'] ? array("rec_URL" => $_REQUEST['URL'], "rec_Modified" => $now) : array("rec_Modified" => $now); mysql__update("Records", "rec_ID={$master_rec_id}", $pairs); //process keeps - which means find repeatables in master record to delete all_details - keeps = deletes //get array of repeatable detail ids for master $master_rep_dt_ids = array(); $res = mysql_query('select rst_DetailTypeID from defRecStructure where rst_MaxValues != 1 and rst_RecTypeID = ' . $_SESSION['rty_ID']); while ($row = mysql_fetch_array($res)) { array_push($master_rep_dt_ids, $row[0]); } $master_rep_detail_ids = array(); foreach ($master_rep_dt_ids as $rep_dt_id) { if (array_key_exists($rep_dt_id, $master_details)) { foreach ($master_details[$rep_dt_id] as $detail) { array_push($master_rep_detail_ids, $detail['dtl_ID']); } } } //get flat array of keep detail ids if ($keep_dt_ids && count($keep_dt_ids)) { $master_keep_ids = array(); foreach ($keep_dt_ids as $dt_id => $details) { foreach ($details as $detail) { array_push($master_keep_ids, $detail); } } } //diff the arrays don't delet yet as the user might be adding an existing value $master_delete_dt_ids = array(); if ($master_rep_detail_ids) { $master_delete_dt_ids = array_diff($master_rep_detail_ids, $master_keep_ids); } //ART HERE $master_keep_ids //FIXME add code to remove any none repeatable extra details //for each update if ($update_dt_ids) { $update_detail = array(); foreach ($update_dt_ids as $rdt_id => $rd_id) { //look up data for detail and $update_detail = mysql_fetch_assoc(mysql_query('select * from recDetails where dtl_ID=' . $rd_id)); // if exist in master details update val if (in_array($rdt_id, array_keys($master_details))) { mysql__update("recDetails", "dtl_ID=" . $master_details[$rdt_id][0]['dtl_ID'], array("dtl_Value" => $update_detail['dtl_Value'])); // else insert the data as detail for master record } else { unset($update_detail['dtl_ID']); //get rid of the detail id the insert will create a new one. $update_detail['dtl_RecID'] = $master_rec_id; // set this as a detail of the master record mysql__insert('recDetails', $update_detail); } } } //process adds if ($add_dt_ids) { $add_details = array(); // for each add detail foreach ($add_dt_ids as $key => $detail_ids) { foreach ($detail_ids as $detail_id) { // since adds are only for repeatables check if it exist in delete array ?yes - remove from delete list if there if ($key_remove = array_search($detail_id, $master_delete_dt_ids) !== FALSE) { //FIXME need to compare teh value not the dtl_ID (they will always be diff) //remove from array unset($master_delete_dt_ids[$key_remove]); } else { //no then lookup data for detail and insert the data as detail under the master rec id $add_detail = mysql_fetch_assoc(mysql_query('select * from recDetails where dtl_ID=' . $detail_id)); unset($add_detail['dtl_ID']); //the id is auto set during insert $add_detail['dtl_RecID'] = $master_rec_id; mysql__insert('recDetails', $add_detail); } } } } foreach ($dup_rec_ids as $dup_rec_id) { //saw FIXME we should be updating the chain of links mysql_query('insert into recForwarding (rfw_OldRecID, rfw_NewRecID) values (' . $dup_rec_id . ', ' . $master_rec_id . ')'); //saw FIXME we should update the relationship table on both rr_rec_idxxx fields } // move dup bookmarks and tags to master unless they are already there //get bookmarkid =>userid for bookmarks of master record $master_bkm_UGrpIDs = mysql__select_assoc('usrBookmarks', 'bkm_ID', 'bkm_UGrpID', 'bkm_recID = ' . $master_rec_id); //get kwd_ids for all bookmarks of master record $master_tag_ids = mysql__select_array('usrRecTagLinks', 'rtl_TagID', 'rtl_RecID = ' . $master_rec_id); //get bookmarkid => userid of bookmarks for dup records $dup_bkm_UGrpIDs = mysql__select_assoc('usrBookmarks', 'bkm_ID', 'bkm_UGrpID', 'bkm_recID in' . $dup_rec_list); // if dup userid already has a bookmark on master record then add dup bkm_ID to delete_bkm_IDs_list else add to update_bkm_IDs $update_bkm_IDs = array(); $delete_bkm_IDs = array(); $dup_delete_bkm_ID_to_master_bkm_id = array(); //for every user or group that bookmarks a dup record if it already bookmarks the master then mark it for deletion // otherwise mark it for update to point to the master record foreach ($dup_bkm_UGrpIDs as $dup_bkm_ID => $dup_bkm_UGrpID) { if (count(@$master_bkm_UGrpIDs) && ($matching_master_bkm_ID = array_search($dup_bkm_UGrpID, $master_bkm_UGrpIDs))) { array_push($delete_bkm_IDs, $dup_bkm_ID); $dup_delete_bkm_ID_to_master_bkm_id[$dup_bkm_ID] = $matching_master_bkm_ID; } else { array_push($update_bkm_IDs, $dup_bkm_ID); $master_bkm_UGrpIDs[$dup_bkm_ID] = $dup_bkm_UGrpID; } } //move duplicate record bookmarks for users without bookmarks on the master record $update_bkm_IDs_list = '(' . join(',', $update_bkm_IDs) . ")"; $delete_bkm_IDs_list = '(' . join(',', $delete_bkm_IDs) . ")"; if (strlen($update_bkm_IDs_list) > 2) { // update the bookmarks and tags that are not in the master mysql_query('update usrBookmarks set bkm_recID=' . $master_rec_id . ' where bkm_ID in ' . $update_bkm_IDs_list); // mysql_query('update usrRecTagLinks set rtl_RecID='.$master_rec_id.' where kwl_pers_id in '.$update_bkm_IDs_list); } // process to be deleted dup bookmarks foreach ($delete_bkm_IDs as $delete_dup_bkm_ID) { //copy soon to be deleted dup bookmark data to master record bookmark by concat notes and pwd_reminder, max of ratings and copy zotero if non existant $master_bkm_ID = @$dup_delete_bkm_ID_to_master_bkm_id[$delete_dup_bkm_ID]; $res1 = mysql_query('select * from usrBookmarks where bkm_ID=' . $master_bkm_ID); $res2 = mysql_query('select * from usrBookmarks where bkm_ID=' . $delete_dup_bkm_ID); if (!($res1 && $res2)) { continue; } $master_pers_record = mysql_fetch_assoc($res1); $delete_dup_pers_record = mysql_fetch_assoc($res2); // $master_pers_record['pers_notes'] .= $delete_dup_pers_record['pers_notes']; $master_pers_record['bkm_PwdReminder'] .= "; " . $delete_dup_pers_record['bkm_PwdReminder']; $master_pers_record['bkm_Rating'] = max($master_pers_record['bkm_Rating'], $delete_dup_pers_record['bkm_Rating']); if (!$master_pers_record['bkm_ZoteroID']) { $master_pers_record['bkm_ZoteroID'] = $delete_dup_pers_record['bkm_ZoteroID']; } unset($master_pers_record['bkm_ID']); mysql__update('usrBookmarks', 'bkm_ID=' . $master_bkm_ID, $master_pers_record); } //for every delete dup tag link whoses tag id is not already linked to the master record change the record id to master //get tag links for the soon to be deleted dup records $delete_dup_rtl_ids = mysql__select_assoc('usrRecTagLinks', 'rtl_ID', 'rtl_TagID', 'rtl_RecID in' . $dup_rec_list); foreach ($delete_dup_rtl_ids as $rtl_ID => $tag_id) { if (count($master_tag_ids) && array_search($tag_id, $master_tag_ids)) { //if it's already linked to the master delete it mysql_query('delete from usrRecTagLinks where rtl_ID = ' . $rtl_ID); //FIXME add error code } else { // otherwise point it to the master record mysql_query('update usrRecTagLinks set rtl_RecID=' . $master_rec_id . ', where rtl_ID = ' . $rtl_ID); array_push($master_tag_ids, $tag_id); // add to the array of tagids already on the master record } } // move reminders to master mysql_query('update usrReminders set rem_RecID=' . $master_rec_id . ' where rem_RecID in ' . $dup_rec_list); //?FIXME do we need to check reminders like we checked usrBookmarks //delete master details if ($master_delete_dt_ids && count($master_delete_dt_ids)) { $master_detail_delete_list = '(' . join(',', $master_delete_dt_ids) . ')'; mysql_query('delete from recDetails where dtl_ID in ' . $master_detail_delete_list); //FIXME add error code } //delete dup details mysql_query('delete from recDetails where dtl_RecID in ' . $dup_rec_list); //delete dup usrBookmarks if (strlen($delete_bkm_IDs_list) > 2) { mysql_query('delete from usrBookmarks where bkm_ID in ' . $delete_bkm_IDs_list); } // move dup record pointers to master record mysql_query('update recDetails left join defDetailTypes on dty_ID=dtl_DetailTypeID set dtl_Value=' . $master_rec_id . ' where dtl_Value in ' . $dup_rec_list . ' and dty_Type="resource"'); //delete dups mysql_query('delete from Records where rec_ID in ' . $dup_rec_list); //delete unwanted details in master //if ($master_delete_dt_ids && $master_delete_dt_ids[0]){ // $master_delete_dt_ids_list = '('.join(',',$master_delete_dt_ids). ')' ; // mysql_query('delete from recDetails where dtl_ID in '.$master_delete_dt_ids_list); // } //try to get the record to update title and hash // calculate title, do an update $type = $_SESSION['rty_ID']; $mask = mysql__select_array("defRecTypes", "rty_TitleMask", "rty_ID=" . $type); if ($mask && count($mask) > 0) { $mask = $mask[0]; $title = fill_title_mask($mask, $master_rec_id, $type); if ($title) { mysql_query("update Records set rec_Title = '" . mysql_real_escape_string($title) . "' where rec_ID = {$master_rec_id}"); } } mysql_query('update Records set rec_Hash = hhash(rec_ID) where rec_ID=' . $master_rec_id); header('Location: combineDuplicateRecords.php?db=' . HEURIST_DBNAME . '&bib_ids=' . $_REQUEST['bib_ids']); }