function handleFileUploads($uploadFile, $formVars) { global $filesBaseDir; // these variables are defined in 'ini.inc.php' global $moveFilesIntoSubDirectories; global $dirNamingScheme; global $renameUploadedFiles; global $fileNamingScheme; global $handleNonASCIIChars; global $allowedFileNameCharacters; global $allowedDirNameCharacters; global $changeCaseInFileNames; global $changeCaseInDirNames; $tmpFilePath = $uploadFile["tmp_name"]; // Generate file name: if ($renameUploadedFiles == "yes") { if (preg_match("/.+\\.[^.]+\$/i", $uploadFile["name"])) { // preserve any existing file name extension $fileNameExtension = preg_replace("/.+(\\.[^.]+)\$/i", "\\1", $uploadFile["name"]); } else { $fileNameExtension = ""; } // auto-generate a file name according to the naming scheme given in '$fileNamingScheme': $newFileName = parsePlaceholderString($formVars, $fileNamingScheme, "<:serial:>"); // function 'parsePlaceholderString()' is defined in 'include.inc.php' // handle non-ASCII and unwanted characters: $newFileName = handleNonASCIIAndUnwantedCharacters($newFileName, $allowedFileNameCharacters, $handleNonASCIIChars); // function 'handleNonASCIIAndUnwantedCharacters()' is defined in 'include.inc.php' // add original file name extension: $newFileName .= $fileNameExtension; } else { // take the file name as given by the user: $newFileName = $uploadFile["name"]; } // Generate directory structure: if ($moveFilesIntoSubDirectories != "never") { // remove any slashes (i.e., directory delimiter(s)) from the beginning or end of '$dirNamingScheme': $dirNamingScheme = trimTextPattern($dirNamingScheme, "[\\/\\\\]+", true, true); // function 'trimTextPattern()' is defined in 'include.inc.php' $dirNamingSchemePartsArray = preg_split("#[/\\\\]+#", $dirNamingScheme); // split on slashes to separate between multiple sub-directories $subDirNamesArray = array(); // initialize array variable which will hold the generated sub-directory names // auto-generate a directory name according to the naming scheme given in '$dirNamingScheme' // and handle non-ASCII chars plus unwanted characters: foreach ($dirNamingSchemePartsArray as $dirNamingSchemePart) { // parse given placeholder string: $subDirName = parsePlaceholderString($formVars, $dirNamingSchemePart, ""); // function 'parsePlaceholderString()' is defined in 'include.inc.php' // handle non-ASCII and unwanted characters: $subDirName = handleNonASCIIAndUnwantedCharacters($subDirName, $allowedDirNameCharacters, $handleNonASCIIChars); // function 'handleNonASCIIAndUnwantedCharacters()' is defined in 'include.inc.php' if (!empty($subDirName)) { $subDirNamesArray[] = $subDirName; } } if (!empty($subDirNamesArray)) { $subDirName = implode("/", $subDirNamesArray) . "/"; } else { $subDirName = ""; } } else { $subDirName = ""; } // Perform any case transformations: // change case of file name: if (preg_match("/^(lower|upper)\$/i", $changeCaseInFileNames)) { $newFileName = changeCase($changeCaseInFileNames, $newFileName); } // function 'changeCase()' is defined in 'include.inc.php' // change case of DIR name: if (preg_match("/^(lower|upper)\$/i", $changeCaseInDirNames) && !empty($subDirName)) { $subDirName = changeCase($changeCaseInDirNames, $subDirName); } // Generate full destination path: // - if '$moveFilesIntoSubDirectories = "existing"' and there's an existing sub-directory (within the default files directory '$filesBaseDir') // whose name equals '$subDirName' we'll copy the new file into that sub-directory // - if '$moveFilesIntoSubDirectories = "always"' and '$subDirName' isn't empty, we'll generate an appropriately named sub-directory if it // doesn't exist yet // - otherwise we just copy the file to the root-level of '$filesBaseDir': if (!empty($subDirName) && ($moveFilesIntoSubDirectories == "existing" and is_dir($filesBaseDir . $subDirName) or $moveFilesIntoSubDirectories == "always")) { $destFilePath = $filesBaseDir . $subDirName . $newFileName; // new file will be copied into sub-directory within '$filesBaseDir'... // copy the new subdir name & file name to the 'file' field variable: // Note: if a user uploads a file and there was already a file specified within the 'file' field, the old file will NOT get removed // from the files directory! Automatic file removal is omitted on purpose since it's way more difficult to recover an // inadvertently deleted file than to delete it manually. However, future versions should introduce a smarter way of handling // orphaned files... $fileName = $subDirName . $newFileName; if ($moveFilesIntoSubDirectories == "always" and !is_dir($filesBaseDir . $subDirName)) { // make sure the directory we're moving the file to exists before proceeding: recursiveMkdir($filesBaseDir . $subDirName); } } else { $destFilePath = $filesBaseDir . $newFileName; // new file will be copied to root-level of '$filesBaseDir'... $fileName = $newFileName; // copy the new file name to the 'file' field variable (see note above!) } // Copy uploaded file from temporary location to the default file directory specified in '$filesBaseDir': // (for more on PHP file uploads see <http://www.php.net/manual/en/features.file-upload.php>) move_uploaded_file($tmpFilePath, $destFilePath); return $fileName; }
function findDuplicates($sqlQuery, $originalDisplayType) { global $tableRefs, $tableUserData; // defined in 'db.inc.php' global $alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, $print, $punct, $space, $upper, $word, $patternModifiers; // defined in 'transtab_unicode_charset.inc.php' and 'transtab_latin1_charset.inc.php' // re-assign the correct display type (i.e. the view that was active when the user clicked the 'dups' link in the header): if (!empty($originalDisplayType)) { $displayType = $originalDisplayType; } // Extract form variables provided by the 'duplicateSearch' form in 'duplicate_search.php': if (isset($_REQUEST['matchFieldsSelector'])) { if (is_string($_REQUEST['matchFieldsSelector'])) { // we accept a string containing a (e.g. comma delimited) list of field names $selectedFieldsArray = preg_split("/[^a-z_]+/", $_REQUEST['matchFieldsSelector'], -1, PREG_SPLIT_NO_EMPTY); } else { // the field list is already provided as array: $selectedFieldsArray = $_REQUEST['matchFieldsSelector']; } } else { $selectedFieldsArray = array(); } if (isset($_REQUEST['ignoreWhitespace']) and $_REQUEST['ignoreWhitespace'] == "1") { $ignoreWhitespace = "1"; } else { $ignoreWhitespace = "0"; } if (isset($_REQUEST['ignorePunctuation']) and $_REQUEST['ignorePunctuation'] == "1") { $ignorePunctuation = "1"; } else { $ignorePunctuation = "0"; } if (isset($_REQUEST['ignoreCharacterCase']) and $_REQUEST['ignoreCharacterCase'] == "1") { $ignoreCharacterCase = "1"; } else { $ignoreCharacterCase = "0"; } if (isset($_REQUEST['ignoreAuthorInitials']) and $_REQUEST['ignoreAuthorInitials'] == "1") { $ignoreAuthorInitials = "1"; } else { $ignoreAuthorInitials = "0"; } if (isset($_REQUEST['nonASCIIChars'])) { $nonASCIIChars = $_REQUEST['nonASCIIChars']; } else { $nonASCIIChars = "keep"; } // VALIDATE FORM DATA: $errors = array(); // Validate the field selector: if (empty($selectedFieldsArray)) { $errors["matchFieldsSelector"] = "You must select at least one field:"; } // Validate the 'SQL Query' field: if (empty($sqlQuery)) { $errors["sqlQuery"] = "You must specify a query string:"; } elseif (!preg_match("/^SELECT/i", $sqlQuery)) { $errors["sqlQuery"] = "You can only execute SELECT queries:"; } // Check if there were any errors: if (count($errors) > 0) { // In case of an error, we write all form variables back to the '$formVars' array // (which 'duplicate_search.php' requires to reload form values): foreach ($_REQUEST as $varname => $value) { $formVars[$varname] = $value; } // Since checkbox form fields do only get included in the '$_REQUEST' array if they were marked, // we have to add appropriate array elements for all checkboxes that weren't set: if (!isset($formVars["ignoreWhitespace"])) { $formVars["ignoreWhitespace"] = "0"; } if (!isset($formVars["ignorePunctuation"])) { $formVars["ignorePunctuation"] = "0"; } if (!isset($formVars["ignoreCharacterCase"])) { $formVars["ignoreCharacterCase"] = "0"; } if (!isset($formVars["ignoreAuthorInitials"])) { $formVars["ignoreAuthorInitials"] = "0"; } if (!isset($formVars["showLinks"])) { $formVars["showLinks"] = "0"; } // Write back session variables: saveSessionVariable("errors", $errors); // function 'saveSessionVariable()' is defined in 'include.inc.php' saveSessionVariable("formVars", $formVars); // There are errors. Relocate back to 'duplicate_search.php': header("Location: duplicate_search.php"); exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< } // CONSTRUCT SQL QUERY (1. DUPLICATE SEARCH): // To identify any duplicates within the results of the original query, we build a new query based on the original SQL query: $query = $sqlQuery; // Replace SELECT list of columns with those from '$selectedFieldsArray' (plus the 'serial' column): $selectedFieldsString = implode(", ", $selectedFieldsArray); $query = newSELECTclause("SELECT " . $selectedFieldsString . ", serial", $query, false); // function 'newSELECTclause()' is defined in 'include.inc.php' // Replace any existing ORDER BY clause with the list of columns given in '$selectedFieldsArray': $query = newORDERclause("ORDER BY " . $selectedFieldsString, $query, false); // function 'newORDERclause()' is defined in 'include.inc.php' // Fix escape sequences within the SQL query: $query = stripSlashesIfMagicQuotes($query); // RUN the query on the database through the connection: $result = queryMySQLDatabase($query); // function 'queryMySQLDatabase()' is defined in 'include.inc.php' // PROCESS RESULTS: $recordSerialsArray = array(); $duplicateRecordSerialsArray = array(); $rowsFound = @mysql_num_rows($result); // Identify any records with matching field data: if ($rowsFound > 0) { // Count the number of fields: $fieldsFound = mysql_num_fields($result); // Loop over each row in the result set: for ($rowCounter = 0; $row = @mysql_fetch_array($result); $rowCounter++) { $recordIdentifier = ""; // make sure our buffer variable is empty // For each row, loop over each field (except for the last one which is the 'serial' field): for ($i = 0; $i < $fieldsFound - 1; $i++) { // fetch the current attribute name: $fieldName = getMySQLFieldInfo($result, $i, "name"); // function 'getMySQLFieldInfo()' is defined in 'include.inc.php' // normalize author names: if ($fieldName == "author" and $ignoreAuthorInitials == "1") { // this is a stupid hack that maps the names of the '$row' array keys to those used // by the '$formVars' array (which is required by function 'parsePlaceholderString()') // (eventually, the '$formVars' array should use the MySQL field names as names for its array keys) $formVars = buildFormVarsArray($row); // function 'buildFormVarsArray()' is defined in 'include.inc.php' // ignore initials in author names: $row[$i] = parsePlaceholderString($formVars, "<:authors[0||]:>", ""); // function 'parsePlaceholderString()' is defined in 'include.inc.php' } $recordIdentifier .= $row[$i]; // merge all field values to form a unique record identifier string } // Normalize record identifier string: if ($ignoreWhitespace == "1") { // ignore whitespace $recordIdentifier = preg_replace("/\\s+/", "", $recordIdentifier); } if ($ignorePunctuation == "1") { // ignore punctuation $recordIdentifier = preg_replace("/[{$punct}]+/{$patternModifiers}", "", $recordIdentifier); } if ($ignoreCharacterCase == "1") { // ignore character case $recordIdentifier = strtolower($recordIdentifier); } if ($nonASCIIChars == "strip") { // strip non-ASCII characters $recordIdentifier = handleNonASCIIAndUnwantedCharacters($recordIdentifier, "\\S\\s", "strip"); } elseif ($nonASCIIChars == "transliterate") { // transliterate non-ASCII characters $recordIdentifier = handleNonASCIIAndUnwantedCharacters($recordIdentifier, "\\S\\s", "transliterate"); } // Check whether the record identifier string has occurred already: if (isset($recordSerialsArray[$recordIdentifier])) { // this record identifier string has already been seen $recordSerialsArray[$recordIdentifier][] = $row["serial"]; } else { // new record identifier string $recordSerialsArray[$recordIdentifier] = array($row["serial"]); } // add a new array element for this record's identifier string (and store its serial number as value within a sub-array) } // Collect all array elements from '$recordSerialsArray' where their sub-array contains more than one serial number: foreach ($recordSerialsArray as $recordSerials) { if (count($recordSerials) > 1) { foreach ($recordSerials as $recordSerial) { $duplicateRecordSerialsArray[] = $recordSerial; } } // add this record's serial number to the array of duplicate record serials } } else { // TODO! } if (empty($duplicateRecordSerialsArray)) { $duplicateRecordSerialsArray[] = "0"; } // if no duplicate records were found, the non-existing serial number '0' will result in a "nothing found" feedback // CONSTRUCT SQL QUERY (2. DUPLICATES DISPLAY): // To display any duplicates that were found within the results of the original query, we build again a new query based on the original SQL query: $query = $sqlQuery; // Replace WHERE clause: // TODO: maybe make this into a generic function? (compare with function 'extractWHEREclause()' in 'include.inc.php') $duplicateRecordSerialsString = implode("|", $duplicateRecordSerialsArray); $query = preg_replace("/(?<=WHERE )(.+?)(?= ORDER BY| LIMIT| GROUP BY| HAVING| PROCEDURE| FOR UPDATE| LOCK IN|[ ;]+(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|FILE)\\b|\$)/i", "serial RLIKE \"^(" . $duplicateRecordSerialsString . ")\$\"", $query); // Replace any existing ORDER BY clause with the list of columns given in '$selectedFieldsArray': $query = newORDERclause("ORDER BY " . $selectedFieldsString, $query, false); return array($query, $displayType); }
function generateCiteKey($formVars) { global $defaultCiteKeyFormat; // defined in 'ini.inc.php' global $handleNonASCIICharsInCiteKeysDefault; global $userOptionsArray; // '$userOptionsArray' is made globally available in file 'import_modify.php' as well as by functions 'generateExport()' and 'generateCitations()' in 'search.php' // by default, we use any record-specific cite key that was entered manually by the user: if (isset($formVars['citeKeyName'])) { $citeKey = $formVars['citeKeyName']; } else { $citeKey = ""; } // check if the user's options for auto-generation of cite keys command us to replace the manually entered cite key: if (!empty($userOptionsArray)) { if ($userOptionsArray['export_cite_keys'] == "yes") { if ($userOptionsArray['autogenerate_cite_keys'] == "yes") { if (empty($citeKey) or $userOptionsArray['prefer_autogenerated_cite_keys'] == "yes") { if ($userOptionsArray['use_custom_cite_key_format'] == "yes") { // if the user wants to use a custom cite key format $citeKeyFormat = $userOptionsArray['cite_key_format']; } else { // use the default cite key format that was specified by the admin in 'ini.inc.php' $citeKeyFormat = $defaultCiteKeyFormat; } // auto-generate a cite key according to the given naming scheme: $citeKey = parsePlaceholderString($formVars, $citeKeyFormat, "<:authors:><:year:>"); } } } else { $citeKey = ""; } // by omitting a cite key Bibutils will take care of generation of cite keys for its export formats (BibTeX, Endnote, RIS) } // check how to handle non-ASCII characters: if (!empty($userOptionsArray) and !empty($userOptionsArray['nonascii_chars_in_cite_keys'])) { // use the user's own setting $handleNonASCIIChars = $userOptionsArray['nonascii_chars_in_cite_keys']; } else { $handleNonASCIIChars = $handleNonASCIICharsInCiteKeysDefault; } // use the default setting that was specified by the admin in 'ini.inc.php' // in addition to the handling of non-ASCII chars (given in '$handleNonASCIIChars') we'll // strip additional characters from the generated cite keys: for cite keys, we only allow // letters, digits, and the following characters: !$&*+-./:;<>?[]^_`| // see e.g. the discussion of cite keys at: <http://search.cpan.org/~gward/btparse-0.34/doc/bt_language.pod> if (!empty($citeKey)) { $citeKey = handleNonASCIIAndUnwantedCharacters($citeKey, "[:alnum:]" . preg_quote("!\$&*+-./:;<>?[]^_`|", "/"), $handleNonASCIIChars); } // ensure that each cite key is unique: if (!empty($citeKey) and !empty($userOptionsArray) and $userOptionsArray['export_cite_keys'] == "yes" and $userOptionsArray['uniquify_duplicate_cite_keys'] == "yes") { // if the generated cite key already exists in the global array of found cite keys // ('$citeKeysArray'), we'll uniquify it, otherwise we'll keep it as is: $citeKey = ensureUniqueCiteKey($citeKey); } return $citeKey; }