You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1452 lines
77 KiB

  1. <?php
  2. // Project: Web Reference Database (refbase) <http://www.refbase.net>
  3. // Copyright: Matthias Steffens <mailto:refbase@extracts.de> and the file's
  4. // original author(s).
  5. //
  6. // This code is distributed in the hope that it will be useful,
  7. // but WITHOUT ANY WARRANTY. Please see the GNU General Public
  8. // License for more details.
  9. //
  10. // File: ./modify.php
  11. // Repository: $HeadURL: file:///svn/p/refbase/code/branches/bleeding-edge/modify.php $
  12. // Author(s): Matthias Steffens <mailto:refbase@extracts.de>
  13. //
  14. // Created: 18-Dec-02, 23:08
  15. // Modified: $Date: 2017-04-13 02:00:18 +0000 (Thu, 13 Apr 2017) $
  16. // $Author: karnesky $
  17. // $Revision: 1416 $
  18. // This php script will perform adding, editing & deleting of records.
  19. // It then calls 'receipt.php' which displays links to the modified/added record
  20. // as well as to the previous search results page (if any).
  21. // TODO: I18n
  22. // Incorporate some include files:
  23. include 'initialize/db.inc.php'; // 'db.inc.php' is included to hide username and password
  24. include 'includes/include.inc.php'; // include common functions
  25. include 'initialize/ini.inc.php'; // include common variables
  26. // --------------------------------------------------------------------
  27. // START A SESSION:
  28. // call the 'start_session()' function (from 'include.inc.php') which will also read out available session variables:
  29. start_session(true);
  30. // --------------------------------------------------------------------
  31. // Initialize preferred display language:
  32. // (note that 'locales.inc.php' has to be included *after* the call to the 'start_session()' function)
  33. include 'includes/locales.inc.php'; // include the locales
  34. // --------------------------------------------------------------------
  35. // Clear any errors that might have been found previously:
  36. $errors = array();
  37. // We check the '$_GET['proc']' variable in addition to '$_POST' in order to catch the case where the POSTed data are
  38. // greater than the value given in 'post_max_size' (in 'php.ini'). This may happen if the user uploads a large file.
  39. // Relevant quote from <http://de.php.net/ini.core>:
  40. // "If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty.
  41. // This can be tracked in various ways, e.g. by passing the $_GET variable to the script processing the data,
  42. // i.e. <form action="edit.php?processed=1">, and then checking if $_GET['processed'] is set."
  43. if (isset($_GET['proc']) AND empty($_POST))
  44. {
  45. $maxPostDataSize = ini_get("post_max_size");
  46. // inform the user that the maximum post data size was exceeded:
  47. $HeaderString = returnMsg($loc["Warning_PostDataSizeMustNotExceed"] . " " . $maxPostDataSize . "!", "warning", "strong", "HeaderString"); // function 'returnMsg()' is defined in 'include.inc.php'
  48. header("Location: " . $referer); // redirect to 'record.php' (variable '$referer' is globally defined in function 'start_session()' in 'include.inc.php')
  49. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  50. }
  51. // Write the (POST) form variables into an array:
  52. foreach($_POST as $varname => $value)
  53. $formVars[$varname] = trim($value); // remove any leading or trailing whitespace from the field's contents & copy the trimmed string to the '$formVars' array
  54. // $formVars[$varname] = trim(clean($value, 50)); // the use of the clean function would be more secure!
  55. // --------------------------------------------------------------------
  56. // Extract form variables sent through POST:
  57. // Note: Although we could use the '$formVars' array directly below (e.g.: $formVars['pageLoginStatus'] etc., like in 'user_validation.php'), we'll read out
  58. // all variables individually again. This is done to enhance readability. (A smarter way of doing so seems be the use of the 'extract()' function, but that
  59. // may expose yet another security hole...)
  60. // Extract the page's login status (which indicates the user's login status at the time the page was loaded):
  61. $pageLoginStatus = $formVars['pageLoginStatus'];
  62. // First of all, check if this script was called by something else than 'record.php':
  63. if (!preg_match("#/record\.php\?.+#", $referer))
  64. {
  65. // return an appropriate error message:
  66. $HeaderString = returnMsg($loc["Warning_InvalidCallToScript"] . " '" . scriptURL() . "'!", "warning", "strong", "HeaderString"); // functions 'returnMsg()' and 'scriptURL()' are defined in 'include.inc.php'
  67. header("Location: " . $referer); // redirect to calling page
  68. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  69. }
  70. // If the referring page is 'record.php' (i.e., if this script was called by 'record.php'), check if the user is logged in:
  71. elseif ((!isset($_SESSION['loginEmail'])) OR ($pageLoginStatus != "logged in")) // if the user isn't logged in -OR- the page's login status still does NOT state "logged in" (since the page wasn't reloaded after the user logged in elsewhere)
  72. {
  73. // the user is logged in BUT the page's login status still does NOT state "logged in" (since the page wasn't reloaded after the user logged IN elsewhere):
  74. if ((isset($_SESSION['loginEmail'])) AND ($pageLoginStatus != "logged in"))
  75. {
  76. // return an appropriate error message:
  77. $HeaderString = returnMsg($loc["Warning_PageStatusOutDated"] . "!", "warning", "strong", "HeaderString", "", "<br>" . $loc["Warning_RecordDataReloaded"] . ":"); // function 'returnMsg()' is defined in 'include.inc.php'
  78. header("Location: " . $referer); // redirect to 'record.php'
  79. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  80. }
  81. // the user is NOT logged in BUT the page's login status still states that he's "logged in" (since the page wasn't reloaded after the user logged OUT elsewhere):
  82. if ((!isset($_SESSION['loginEmail'])) AND ($pageLoginStatus == "logged in"))
  83. {
  84. // return an appropriate error message:
  85. $HeaderString = returnMsg($loc["Warning_NotLoggedInAnymore"] . "!", "warning", "strong", "HeaderString", "", "<br>" . $loc["Warning_TimeOutPleaseLoginAgain"] . ":"); // function 'returnMsg()' is defined in 'include.inc.php'
  86. }
  87. // else if the user isn't logged in yet: ((!isset($_SESSION['loginEmail'])) AND ($pageLoginStatus != "logged in"))
  88. header("Location: user_login.php?referer=" . rawurlencode($referer)); // ask the user to login first, then he'll get directed back to 'record.php'
  89. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  90. }
  91. // if we made it here, the user is regularly logged in: (isset($_SESSION['loginEmail'] == true) AND ($pageLoginStatus == "logged in")
  92. // Extract the form used by the user:
  93. $formType = $formVars['formType'];
  94. // Extract the type of action requested by the user (either 'add', 'edit' or ''):
  95. $recordAction = $formVars['recordAction'];
  96. // $recordAction == '' will be treated equal to 'add':
  97. if (empty($recordAction))
  98. $recordAction = "add"; // we set it explicitly here so that we can employ this variable within message strings, etc
  99. // Determine the button that was hit by the user (either 'Add Record', 'Edit Record', 'Delete Record' or ''):
  100. // '$submitAction' is only used to determine any 'delet' action! (where '$submitAction' = 'Delete Record')
  101. // (otherwise, only '$recordAction' controls how to proceed)
  102. $submitAction = $formVars['submit'];
  103. if (encodeHTML($submitAction) == $loc["ButtonTitle_DeleteRecord"]) // note that we need to HTML encode '$submitAction' for comparison with the HTML encoded locales
  104. $recordAction = "delet"; // *delete* record
  105. // now, check if the (logged in) user is allowed to perform the current record action (i.e., add, edit or delete a record):
  106. $notPermitted = false;
  107. // if the (logged in) user...
  108. if ($recordAction == "edit") // ...wants to edit the current record...
  109. {
  110. if (isset($_SESSION['user_permissions']) AND !preg_match("/allow_edit/", $_SESSION['user_permissions'])) // ...BUT the 'user_permissions' session variable does NOT contain 'allow_edit'...
  111. {
  112. $notPermitted = true;
  113. $HeaderString = $loc["NoPermission"] . $loc["NoPermission_ForEditRecord"] . "!";
  114. }
  115. }
  116. elseif ($recordAction == "delet") // ...wants to delete the current record...
  117. {
  118. if (isset($_SESSION['user_permissions']) AND !preg_match("/allow_delete/", $_SESSION['user_permissions'])) // ...BUT the 'user_permissions' session variable does NOT contain 'allow_delete'...
  119. {
  120. $notPermitted = true;
  121. $HeaderString = $loc["NoPermission"] . $loc["NoPermission_ForDeleteRecord"] . "!";
  122. }
  123. }
  124. else // if ($recordAction == "add" OR $recordAction == "") // ...wants to add the current record...
  125. {
  126. if (isset($_SESSION['user_permissions']) AND !preg_match("/allow_add/", $_SESSION['user_permissions'])) // ...BUT the 'user_permissions' session variable does NOT contain 'allow_add'...
  127. {
  128. $notPermitted = true;
  129. $HeaderString = $loc["NoPermission"] . $loc["NoPermission_ForAddRecords"] . "!";
  130. }
  131. }
  132. if ($notPermitted)
  133. {
  134. // return an appropriate error message:
  135. $HeaderString = returnMsg($HeaderString, "warning", "strong", "HeaderString"); // function 'returnMsg()' is defined in 'include.inc.php'
  136. header("Location: " . $referer); // redirect to 'record.php'
  137. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  138. }
  139. // if we made it here, we assume that the user is allowed to perform the current record action
  140. // Get the query URL of the formerly displayed results page:
  141. if (isset($_SESSION['oldQuery']))
  142. $oldQuery = $_SESSION['oldQuery'];
  143. else
  144. $oldQuery = array();
  145. // Get the query URL of the last multi-record query:
  146. if (isset($_SESSION['oldMultiRecordQuery']))
  147. $oldMultiRecordQuery = $_SESSION['oldMultiRecordQuery'];
  148. else
  149. $oldMultiRecordQuery = "";
  150. // (1) OPEN CONNECTION, (2) SELECT DATABASE
  151. connectToMySQLDatabase(); // function 'connectToMySQLDatabase()' is defined in 'include.inc.php'
  152. // Extract all form values provided by 'record.php':
  153. if (isset($formVars['authorName']))
  154. $authorName = $formVars['authorName'];
  155. else
  156. $authorName = "";
  157. if (isset($formVars['isEditorCheckBox']))
  158. $isEditorCheckBox = $formVars['isEditorCheckBox'];
  159. else
  160. $isEditorCheckBox = "";
  161. if (isset($formVars['titleName']))
  162. $titleName = $formVars['titleName'];
  163. else
  164. $titleName = "";
  165. if (isset($formVars['yearNo']))
  166. $yearNo = $formVars['yearNo'];
  167. else
  168. $yearNo = "";
  169. if (isset($formVars['publicationName']))
  170. $publicationName = $formVars['publicationName'];
  171. else
  172. $publicationName = "";
  173. if (isset($formVars['abbrevJournalName']))
  174. $abbrevJournalName = $formVars['abbrevJournalName'];
  175. else
  176. $abbrevJournalName = "";
  177. if (isset($formVars['volumeNo']))
  178. $volumeNo = $formVars['volumeNo'];
  179. else
  180. $volumeNo = "";
  181. if (isset($formVars['issueNo']))
  182. $issueNo = $formVars['issueNo'];
  183. else
  184. $issueNo = "";
  185. if (isset($formVars['pagesNo']))
  186. $pagesNo = $formVars['pagesNo'];
  187. else
  188. $pagesNo = "";
  189. if (isset($formVars['addressName']))
  190. $addressName = $formVars['addressName'];
  191. else
  192. $addressName = "";
  193. if (isset($formVars['corporateAuthorName']))
  194. $corporateAuthorName = $formVars['corporateAuthorName'];
  195. else
  196. $corporateAuthorName = "";
  197. if (isset($formVars['keywordsName']))
  198. $keywordsName = $formVars['keywordsName'];
  199. else
  200. $keywordsName = "";
  201. if (isset($formVars['abstractName']))
  202. $abstractName = $formVars['abstractName'];
  203. else
  204. $abstractName = "";
  205. if (isset($formVars['publisherName']))
  206. $publisherName = $formVars['publisherName'];
  207. else
  208. $publisherName = "";
  209. if (isset($formVars['placeName']))
  210. $placeName = $formVars['placeName'];
  211. else
  212. $placeName = "";
  213. if (isset($formVars['editorName']))
  214. $editorName = $formVars['editorName'];
  215. else
  216. $editorName = "";
  217. if (isset($formVars['languageName']))
  218. $languageName = $formVars['languageName'];
  219. else
  220. $languageName = "";
  221. if (isset($formVars['summaryLanguageName']))
  222. $summaryLanguageName = $formVars['summaryLanguageName'];
  223. else
  224. $summaryLanguageName = "";
  225. if (isset($formVars['origTitleName']))
  226. $origTitleName = $formVars['origTitleName'];
  227. else
  228. $origTitleName = "";
  229. if (isset($formVars['seriesEditorName']))
  230. $seriesEditorName = $formVars['seriesEditorName'];
  231. else
  232. $seriesEditorName = "";
  233. if (isset($formVars['seriesTitleName']))
  234. $seriesTitleName = $formVars['seriesTitleName'];
  235. else
  236. $seriesTitleName = "";
  237. if (isset($formVars['abbrevSeriesTitleName']))
  238. $abbrevSeriesTitleName = $formVars['abbrevSeriesTitleName'];
  239. else
  240. $abbrevSeriesTitleName = "";
  241. if (isset($formVars['seriesVolumeNo']))
  242. $seriesVolumeNo = $formVars['seriesVolumeNo'];
  243. else
  244. $seriesVolumeNo = "";
  245. if (isset($formVars['seriesIssueNo']))
  246. $seriesIssueNo = $formVars['seriesIssueNo'];
  247. else
  248. $seriesIssueNo = "";
  249. if (isset($formVars['editionNo']))
  250. $editionNo = $formVars['editionNo'];
  251. else
  252. $editionNo = "";
  253. if (isset($formVars['issnName']))
  254. $issnName = $formVars['issnName'];
  255. else
  256. $issnName = "";
  257. if (isset($formVars['isbnName']))
  258. $isbnName = $formVars['isbnName'];
  259. else
  260. $isbnName = "";
  261. if (isset($formVars['mediumName']))
  262. $mediumName = $formVars['mediumName'];
  263. else
  264. $mediumName = "";
  265. if (isset($formVars['areaName']))
  266. $areaName = $formVars['areaName'];
  267. else
  268. $areaName = "";
  269. if (isset($formVars['expeditionName']))
  270. $expeditionName = $formVars['expeditionName'];
  271. else
  272. $expeditionName = "";
  273. if (isset($formVars['conferenceName']))
  274. $conferenceName = $formVars['conferenceName'];
  275. else
  276. $conferenceName = "";
  277. if (isset($formVars['notesName']))
  278. $notesName = $formVars['notesName'];
  279. else
  280. $notesName = "";
  281. if (isset($formVars['approvedRadio']))
  282. $approvedRadio = $formVars['approvedRadio'];
  283. else
  284. $approvedRadio = "";
  285. if (isset($formVars['locationName']))
  286. $locationName = $formVars['locationName'];
  287. else
  288. $locationName = "";
  289. $callNumberName = $formVars['callNumberName'];
  290. if (preg_match("/%40|%20/", $callNumberName)) // if '$callNumberName' still contains URL encoded data... ('%40' is the URL encoded form of the character '@', '%20' a space, see note below!)
  291. $callNumberName = rawurldecode($callNumberName); // ...URL decode 'callNumberName' variable contents (it was URL encoded before incorporation into a hidden tag of the 'record' form to avoid any HTML syntax errors)
  292. // NOTE: URL encoded data that are included within a *link* will get URL decoded automatically *before* extraction via '$_POST'!
  293. // But, opposed to that, URL encoded data that are included within a form by means of a *hidden form tag* will NOT get URL decoded automatically! Then, URL decoding has to be done manually (as is done here)!
  294. if (isset($formVars['callNumberNameUserOnly']))
  295. $callNumberNameUserOnly = $formVars['callNumberNameUserOnly'];
  296. else
  297. $callNumberNameUserOnly = "";
  298. if (isset($formVars['serialNo']))
  299. $serialNo = $formVars['serialNo'];
  300. else
  301. $serialNo = "";
  302. if (isset($formVars['typeName'])) {
  303. $types = array('Journal Article','Abstract','Book Chapter','Book Whole','Conference Article','Conference Volume','Journal','Magazine Article','Manual','Manuscript','Map','Miscellaneous','Newspaper Article','Patent','Report','Software');
  304. if (in_array($formVars['typeName'],$types))
  305. $typeName = $formVars['typeName'];
  306. else
  307. $typeName = "";
  308. } else
  309. $typeName = "";
  310. if (isset($formVars['thesisName']))
  311. $thesisName = $formVars['thesisName'];
  312. else
  313. $thesisName = "";
  314. if (isset($formVars['markedRadio']))
  315. $markedRadio = $formVars['markedRadio'];
  316. else
  317. $markedRadio = "";
  318. if (isset($formVars['copyName']))
  319. $copyName = $formVars['copyName'];
  320. else
  321. $copyName = "";
  322. if (isset($formVars['selectedRadio']))
  323. $selectedRadio = $formVars['selectedRadio'];
  324. else
  325. $selectedRadio = "";
  326. if (isset($formVars['userKeysName']))
  327. $userKeysName = $formVars['userKeysName'];
  328. else
  329. $userKeysName = "";
  330. if (isset($formVars['userNotesName']))
  331. $userNotesName = $formVars['userNotesName'];
  332. else
  333. $userNotesName = "";
  334. if (isset($formVars['userFileName']))
  335. $userFileName = $formVars['userFileName'];
  336. else
  337. $userFileName = "";
  338. if (isset($formVars['userGroupsName']))
  339. $userGroupsName = $formVars['userGroupsName'];
  340. else
  341. $userGroupsName = "";
  342. if (isset($formVars['citeKeyName']))
  343. $citeKeyName = $formVars['citeKeyName'];
  344. else
  345. $citeKeyName = "";
  346. if (isset($formVars['relatedName']))
  347. $relatedName = $formVars['relatedName'];
  348. else
  349. $relatedName = "";
  350. // if the current user has no permission to download (and hence view) any files, 'record.php' does only show an empty string
  351. // in the 'file' field (no matter if a file exists for the given record or not). Thus, we need to make sure that the empty
  352. // form value won't overwrite any existing contents of the 'file' field on UPDATE and that the correct field value gets
  353. // transferred to table 'deleted' on DELETE:
  354. // Therefore, we re-fetch the contents of the 'file' field if NONE of the following conditions are met:
  355. // - the variable '$fileVisibility' (defined in 'ini.inc.php') is set to 'everyone'
  356. // - the variable '$fileVisibility' is set to 'login' AND the user is logged in
  357. // - the variable '$fileVisibility' is set to 'user-specific' AND the 'user_permissions' session variable contains 'allow_download'
  358. if (preg_match("/^(edit|delet)$/", $recordAction) AND (!($fileVisibility == "everyone" OR ($fileVisibility == "login" AND isset($_SESSION['loginEmail'])) OR ($fileVisibility == "user-specific" AND (isset($_SESSION['user_permissions']) AND preg_match("/allow_download/", $_SESSION['user_permissions'])))))) // user has NO permission to download (and view) any files
  359. {
  360. $queryFile = "SELECT file FROM $tableRefs WHERE serial = " . quote_smart($serialNo);
  361. $result = queryMySQLDatabase($queryFile); // RUN the query on the database through the connection
  362. $row = @ mysqli_fetch_array($result);
  363. $fileName = $row["file"];
  364. }
  365. else // user has permission to download (and view) any files
  366. $fileName = $formVars['fileName'];
  367. if (isset($formVars['urlName']))
  368. $urlName = $formVars['urlName'];
  369. else
  370. $urlName = "";
  371. if (isset($formVars['doiName']))
  372. $doiName = $formVars['doiName'];
  373. else
  374. $doiName = "";
  375. if (isset($formVars['contributionIDName']))
  376. $contributionID = $formVars['contributionIDName'];
  377. else
  378. $contributionID = "";
  379. $contributionID = rawurldecode($contributionID); // URL decode 'contributionID' variable contents (it was URL encoded before incorporation into a hidden tag of the 'record' form to avoid any HTML syntax errors) [see above!]
  380. if (isset($formVars['contributionIDCheckBox']))
  381. $contributionIDCheckBox = $formVars['contributionIDCheckBox'];
  382. else
  383. $contributionIDCheckBox = "";
  384. if (isset($formVars['locationSelectorName']))
  385. $locationSelectorName = $formVars['locationSelectorName'];
  386. else
  387. $locationSelectorName = "";
  388. if (isset($formVars['onlinePublicationCheckBox']))
  389. $onlinePublicationCheckBox = $formVars['onlinePublicationCheckBox'];
  390. else
  391. $onlinePublicationCheckBox = "";
  392. if (isset($formVars['onlineCitationName']))
  393. $onlineCitationName = $formVars['onlineCitationName'];
  394. else
  395. $onlineCitationName = "";
  396. if (isset($formVars['createdDate']))
  397. $createdDate = $formVars['createdDate'];
  398. else
  399. $createdDate = "";
  400. if (isset($formVars['createdTime']))
  401. $createdTime = $formVars['createdTime'];
  402. else
  403. $createdTime = "";
  404. if (isset($formVars['createdBy']))
  405. $createdBy = $formVars['createdBy'];
  406. else
  407. $createdBy = "";
  408. if (isset($formVars['modifiedDate']))
  409. $modifiedDate = $formVars['modifiedDate'];
  410. else
  411. $modifiedDate = "";
  412. if (isset($formVars['modifiedTime']))
  413. $modifiedTime = $formVars['modifiedTime'];
  414. else
  415. $modifiedTime = "";
  416. if (isset($formVars['modifiedBy']))
  417. $modifiedBy = $formVars['modifiedBy'];
  418. else
  419. $modifiedBy = "";
  420. if (isset($formVars['origRecord']))
  421. $origRecord = $formVars['origRecord'];
  422. else
  423. $origRecord = "";
  424. // check if a file was uploaded:
  425. // (note that to have file uploads work, HTTP file uploads must be allowed within your 'php.ini' configuration file
  426. // by setting the 'file_uploads' parameter to 'On'!)
  427. // extract file information into a four (or five) element associative array containing the following information about the file:
  428. // name - original name of file on client
  429. // type - MIME type of file
  430. // tmp_name - name of temporary file on server
  431. // error - holds an error number >0 if something went wrong, otherwise 0 (I don't know when this element was added. It may not be present in your PHP version... ?:-/)
  432. // size - size of file in bytes
  433. // depending what happend on upload, they will contain the following values (PHP 4.1 and above):
  434. // no file upload upload exceeds 'upload_max_filesize' successful upload
  435. // -------------- ------------------------------------ -----------------
  436. // name "" [name] [name]
  437. // type "" "" [type]
  438. // tmp_name "" OR "none" "" [tmp_name]
  439. // error 4 1 0
  440. // size 0 0 [size]
  441. $uploadFile = getUploadInfo("uploadFile"); // function 'getUploadInfo()' is defined in 'include.inc.php'
  442. // --------------------------------------------------------------------
  443. // VALIDATE data fields:
  444. // NOTE: for all fields that are validated here must exist error parsing code (of the form: " . fieldError("languageName", $errors) . ")
  445. // in front of the respective <input> form field in 'record.php'! Otherwise the generated error won't be displayed!
  446. // Validate fields that MUST not be empty:
  447. // Validate the 'Call Number' field:
  448. if (preg_match("/[@;]/", $callNumberNameUserOnly))
  449. $errors["callNumberNameUserOnly"] = "Your call number cannot contain the characters '@' and ';' (since they function as delimiters):"; // the user's personal reference ID cannot contain the characters '@' and ';' since they are used as delimiters (within or between call numbers)
  450. elseif ($recordAction == "edit" AND !empty($callNumberNameUserOnly) AND !preg_match("/$loginEmail/", $locationName) AND !preg_match("/^(add|remove)$/", $locationSelectorName)) // if the user specified some reference ID within an 'edit' action -BUT- there's no existing call number for this user within the contents of the 'location' field -AND- the user doesn't want to add it either...
  451. $errors["callNumberNameUserOnly"] = "You cannot specify a call number unless you add this record to your personal literature set! This can be done by setting the 'Location Field' popup below to 'add'."; // warn the user that he/she has to set the Location Field popup to 'add' if he want's to add this record to his personal literature set
  452. // Validate the 'uploadFile' field:
  453. // (whose file name characters must be within [a-zA-Z0-9+_.-] and which must not exceed
  454. // the 'upload_max_filesize' specified within your 'php.ini' configuration file)
  455. if (!empty($uploadFile) && !empty($uploadFile["name"])) // if the user attempted to upload a file
  456. {
  457. // The 'is_uploaded_file()' function returns 'true' if the file indicated by '$uploadFile["tmp_name"]' was uploaded via HTTP POST. This is useful to help ensure
  458. // that a malicious user hasn't tried to trick the script into working on files upon which it should not be working - for instance, /etc/passwd.
  459. if (is_uploaded_file($uploadFile["tmp_name"]))
  460. {
  461. if (empty($uploadFile["tmp_name"])) // no tmp file exists => we assume that the maximum upload file size was exceeded!
  462. // or check via 'error' element instead: "if ($uploadFile["error"] == 1)" (the 'error' element exists since PHP 4.2.0)
  463. {
  464. $maxFileSize = ini_get("upload_max_filesize");
  465. $fileError = "File size must not be greater than " . $maxFileSize . ":";
  466. $errors["uploadFile"] = $fileError; // inform the user that the maximum upload file size was exceeded
  467. }
  468. else // a tmp file exists...
  469. {
  470. // prevent hackers from gaining access to the systems 'passwd' file (this should be prevented by the 'is_uploaded_file()' function but anyhow):
  471. if (preg_match("/^passwd$/i", $uploadFile["name"])) // file name must not be 'passwd'
  472. $errors["uploadFile"] = "This file name is not allowed!";
  473. // check for invalid file name extensions:
  474. if (preg_match("#\.(exe|com|bat|zip|php|phps|php3|phtml|phtm|cgi)$#i", $uploadFile["name"])) // file name has an invalid file name extension (adjust the regex pattern if you want more relaxed file name validation)
  475. $errors["uploadFile"] = "You cannot upload this type of file!"; // file name must not end with .exe, .com, .bat, .zip, .php, .phps, .php3, .phtml, .phtm or .cgi
  476. if ($renameUploadedFiles != "yes") // if we do NOT rename files according to a standard naming scheme (variable '$renameUploadedFiles' is defined in 'ini.inc.php')
  477. {
  478. // check for invalid file name characters:
  479. if (!preg_match("/^[" . $allowedFileNameCharacters . "]+$/", $uploadFile["name"])) // file name contains invalid characters (variable '$allowedFileNameCharacters' is defined in 'ini.inc.php')
  480. $errors["uploadFile"] = "File name characters can only be within " . $allowedFileNameCharacters; // characters of file name must be within range given in '$allowedFileNameCharacters'
  481. // previous error message was a bit more user-friendly: "File name characters can only be alphanumeric ('a-zA-Z0-9'), plus ('+'), minus ('-'), substring ('_') or a dot ('.'):"
  482. }
  483. }
  484. }
  485. else
  486. {
  487. // I'm not sure if this actually works --RAK
  488. switch($uploadFile["error"])
  489. {
  490. case 0: // no error; possible file attack!
  491. $errors["uploadFile"] = "There was a problem with your upload.";
  492. break;
  493. case 1: // uploaded file exceeds the 'upload_max_filesize' directive in 'php.ini'
  494. $maxFileSize = ini_get("upload_max_filesize");
  495. $fileError = "File size must not be greater than " . $maxFileSize . ":";
  496. $errors["uploadFile"] = $fileError;
  497. break;
  498. case 2: // uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form (Note: refbase doesn't currently specify MAX_FILE_SIZE but anyhow...)
  499. $errors["uploadFile"] = "The file you are trying to upload is too big.";
  500. break;
  501. case 3: // uploaded file was only partially uploaded
  502. $errors["uploadFile"] = "The file you are trying to upload was only partially uploaded.";
  503. break;
  504. case 4: // no file was uploaded
  505. $errors["uploadFile"] = "You must select a file for upload.";
  506. break;
  507. case 6:
  508. $errors["uploadFile"] = "Missing a temporary folder.";
  509. break;
  510. default: // a default error, just in case! :)
  511. $errors["uploadFile"] = "There was a problem with your upload.";
  512. break;
  513. }
  514. }
  515. }
  516. // CAUTION: validation of other fields is currently disabled, since, IMHO, there are too many open questions how to implement this properly
  517. // and without frustrating the user! Uncomment the commented code below to enable the current validation features:
  518. // // Validate fields that SHOULD not be empty:
  519. // // Validate the 'Author' field:
  520. // if (empty($authorName))
  521. // $errors["authorName"] = "Is there really no author info for this record? Enter NULL to force empty:"; // Author should not be a null string
  522. //
  523. // // Validate the 'Title' field:
  524. // if (empty($titleName))
  525. // $errors["titleName"] = "Is there really no title info for this record? Enter NULL to force empty:"; // Title should not be a null string
  526. //
  527. // // Validate the 'Year' field:
  528. // if (empty($yearNo))
  529. // $errors["yearNo"] = "Is there really no year info for this record? Enter NULL to force empty:"; // Year should not be a null string
  530. //
  531. // // Validate the 'Publication' field:
  532. // if (empty($publicationName))
  533. // $errors["publicationName"] = "Is there really no publication info for this record? Enter NULL to force empty:"; // Publication should not be a null string
  534. //
  535. // // Validate the 'Abbrev Journal' field:
  536. // if (empty($abbrevJournalName))
  537. // $errors["abbrevJournalName"] = "Is there really no abbreviated journal info for this record? Enter NULL to force empty:"; // Abbrev Journal should not be a null string
  538. //
  539. // // Validate the 'Volume' field:
  540. // if (empty($volumeNo))
  541. // $errors["volumeNo"] = "Is there really no volume info for this record? Enter NULL to force empty:"; // Volume should not be a null string
  542. //
  543. // // Validate the 'Pages' field:
  544. // if (empty($pagesNo))
  545. // $errors["pagesNo"] = "Is there really no pages info for this record? Enter NULL to force empty:"; // Pages should not be a null string
  546. //
  547. //
  548. // // Validate fields that MUST not be empty:
  549. // // Validate the 'Language' field:
  550. // if (empty($languageName))
  551. // $errors["languageName"] = "The language field cannot be blank:"; // Language cannot be a null string
  552. //
  553. //
  554. // // Remove 'NULL' values that were entered by the user in order to force empty values for required text fields:
  555. // // (for the required number fields 'yearNo' & 'volumeNo' inserting 'NULL' will cause '0000' or '0' as value, respectively)
  556. // if ($authorName == "NULL")
  557. // $authorName = "";
  558. //
  559. // if ($titleName == "NULL")
  560. // $titleName = "";
  561. //
  562. // if ($publicationName == "NULL")
  563. // $publicationName = "";
  564. //
  565. // if ($abbrevJournalName == "NULL")
  566. // $abbrevJournalName = "";
  567. //
  568. // if ($pagesNo == "NULL")
  569. // $pagesNo = "";
  570. // --------------------------------------------------------------------
  571. // Now the script has finished the validation, check if there were any errors:
  572. if (count($errors) > 0)
  573. {
  574. // Write back session variables:
  575. saveSessionVariable("errors", $errors); // function 'saveSessionVariable()' is defined in 'include.inc.php'
  576. saveSessionVariable("formVars", $formVars);
  577. // There are errors. Relocate back to the record entry form:
  578. header("Location: " . $referer);
  579. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  580. }
  581. // --------------------------------------------------------------------
  582. // If we made it here, then the data is considered valid!
  583. // CONSTRUCT SQL QUERY:
  584. // First, setup some required variables:
  585. // Get the current date (e.g. '2003-12-31'), time (e.g. '23:59:49') and user name & email address (e.g. 'Matthias Steffens (refbase@extracts.de)'):
  586. list ($currentDate, $currentTime, $currentUser) = getCurrentDateTimeUser(); // function 'getCurrentDateTimeUser()' is defined in 'include.inc.php'
  587. // Build a correct call number prefix for the currently logged-in user (e.g. 'IP� @ msteffens'):
  588. $callNumberPrefix = getCallNumberPrefix(); // function 'getCallNumberPrefix()' is defined in 'include.inc.php'
  589. // provide some magic that figures out what do to depending on the state of the 'is Editor' check box
  590. // and the content of the 'author', 'editor' and 'type' fields:
  591. if ($isEditorCheckBox == "1" OR preg_match("/^(Book Whole|Conference Volume|Journal|Manuscript|Map)$/", $typeName)) // if the user did mark the 'is Editor' checkbox -OR- if the record type is either 'Book Whole', 'Conference Volume', 'Journal', 'Map' or 'Manuscript'...
  592. if (!empty($editorName) AND empty($authorName)) // ...and if the 'Editor' field has some content while the 'Author' field is blank...
  593. {
  594. $authorName = $editorName; // duplicate field contents from 'editor' to 'author' field
  595. $isEditorCheckBox = "1"; // since the user entered something in the 'editor' field (but not the 'author' field), we need to make sure that the 'is Editor' is marked
  596. }
  597. if ($isEditorCheckBox == "1" AND preg_match("/^(Book Whole|Conference Volume|Journal|Manuscript|Map)$/", $typeName)) // if the user did mark the 'is Editor' checkbox -AND- the record type is either 'Book Whole', 'Conference Volume', 'Journal', 'Map' or 'Manuscript'...
  598. {
  599. $authorName = preg_replace("/ *\(eds?\)$/i","",$authorName); // ...remove any existing editor info from the 'author' string, i.e., kill any trailing " (ed)" or " (eds)"
  600. if (!empty($authorName)) // if the 'Author' field has some content...
  601. $editorName = $authorName; // ...duplicate field contents from 'author' to 'editor' field (CAUTION: this will overwrite any existing contents in the 'editor' field!)
  602. if (!empty($authorName)) // if 'author' field isn't empty
  603. {
  604. if (!preg_match("/;/", $authorName)) // if the 'author' field does NOT contain a ';' (which would delimit multiple authors) => single author
  605. $authorName .= " (ed)"; // append " (ed)" to the end of the 'author' string
  606. else // the 'author' field does contain at least one ';' => multiple authors
  607. $authorName .= " (eds)"; // append " (eds)" to the end of the 'author' string
  608. }
  609. }
  610. else // the 'is Editor' checkbox is NOT checked -OR- the record type is NOT 'Book Whole', 'Conference Volume', 'Journal', 'Map' or 'Manuscript'...
  611. {
  612. if (preg_match("/ *\(eds?\)$/", $authorName)) // if 'author' field ends with either " (ed)" or " (eds)"
  613. $authorName = preg_replace("/ *\(eds?\)$/i","",$authorName); // remove any existing editor info from the 'author' string, i.e., kill any trailing " (ed)" or " (eds)"
  614. if ($authorName == $editorName) // if the 'Author' field contents equal the 'Editor' field contents...
  615. $editorName = ""; // ...clear contents of 'editor' field (that is, we assume that the user did uncheck the 'is Editor' checkbox, which was previously marked)
  616. }
  617. // Assign correct values to the calculation fields 'first_author', 'author_count', 'first_page', 'volume_numeric' and 'series_volume_numeric':
  618. // function 'generateCalculationFieldContent()' is defined in 'include.inc.php'
  619. // NOTE: this function call won't be necessary anymore when we've also moved database INSERTs and DELETEs to dedicated functions (which would take care of calculation fields then) -> compare with 'addRecords()' function
  620. list ($firstAuthor, $authorCount, $firstPage, $volumeNumericNo, $seriesVolumeNumericNo) = generateCalculationFieldContent($authorName, $pagesNo, $volumeNo, $seriesVolumeNo);
  621. // manage 'location' field data:
  622. if ((($locationSelectorName == "add") OR ($locationSelectorName == "")) AND (!preg_match("/$loginEmail/", $locationName))) // add the current user to the 'location' field (if he/she isn't listed already within the 'location' field):
  623. // note: if the current user is NOT logged in -OR- if any normal user is logged in, the value for '$locationSelectorName' will be always '' when performing an INSERT,
  624. // since the popup is fixed to 'add' and disabled (which, in turn, will result in an empty value to be returned)
  625. {
  626. // if the 'location' field is either completely empty -OR- does only contain the information string (that shows up on 'add' for normal users):
  627. if (preg_match("/^(" . $loc["your name & email address will be filled in automatically"] . ")?$/", encodeHTML($locationName))) // note that we need to HTML encode '$locationName' for comparison with the HTML encoded locales
  628. $locationName = preg_replace("/^.*$/i", "$currentUser", $locationName);
  629. else // if the 'location' field does already contain some user content:
  630. $locationName = preg_replace("/^(.+)$/i", "\\1; $currentUser", $locationName);
  631. }
  632. elseif ($locationSelectorName == "remove") // remove the current user from the 'location' field:
  633. { // the only pattern that's really unique is the users email address, the user's name may change (since it can be modified by the user). This is why we dont use '$currentUser' here:
  634. $locationName = preg_replace("/^[^;]*\( *$loginEmail *\) *; */i", "", $locationName); // the current user is listed at the very beginning of the 'location' field
  635. $locationName = preg_replace("/ *;[^;]*\( *$loginEmail *\) */i", "", $locationName); // the current user occurs after some other user within the 'location' field
  636. $locationName = preg_replace("/^[^;]*\( *$loginEmail *\) *$/i", "", $locationName); // the current user is the only one listed within the 'location' field
  637. }
  638. // else if '$locationSelectorName' == "don't touch" -OR- if the user is already listed within the 'location' field, we just accept the contents of the 'location' field as entered by the user
  639. // manage 'call_number' field data:
  640. if ($loginEmail != $adminLoginEmail) // if any normal user is logged in (not the admin):
  641. {
  642. if (preg_match("/$loginEmail/", $locationName)) // we only process the user's call number information if the current user is listed within the 'location' field:
  643. {
  644. // Note that, for normal users, we process the user's call number information even if the '$locationSelectorName' is NOT set to 'add'.
  645. // This is done, since the user should be able to update his/her personal reference ID while the '$locationSelectorName' is set to 'don't touch'.
  646. // If the '$locationSelectorName' is set to 'remove', then any changes made to the personal reference ID will be discarded anyhow.
  647. // build a correct call number string for the current user & record:
  648. if ($callNumberNameUserOnly == "") // if the user didn't enter any personal reference ID for this record...
  649. $callNumberNameUserOnly = $callNumberPrefix . " @ "; // ...insert the user's call number prefix only
  650. else // if the user entered (or modified) his/her personal reference ID for this record...
  651. $callNumberNameUserOnly = $callNumberPrefix . " @ " . $callNumberNameUserOnly; // ...prefix the entered reference ID with the user's call number prefix
  652. // insert or update the user's call number within the full contents of the 'call_number' field:
  653. if ($callNumberName == "") // if the 'call_number' field is empty...
  654. $callNumberName = $callNumberNameUserOnly; // ...insert the user's call number prefix
  655. elseif (preg_match("/$callNumberPrefix/", $callNumberName)) // if the user's call number prefix occurs within the contents of the 'call_number' field...
  656. $callNumberName = preg_replace("/$callNumberPrefix *@ *[^@;]*/i", "$callNumberNameUserOnly", $callNumberName); // ...replace the user's *own* call number within the full contents of the 'call_number' field
  657. else // if the 'call_number' field does already have some content -BUT- there's no existing call number prefix for the current user...
  658. $callNumberName = $callNumberName . "; " . $callNumberNameUserOnly; // ...append the user's call number to any existing call numbers
  659. }
  660. }
  661. else // if the admin is logged in:
  662. if ($locationSelectorName == "add") // we only add the admin's call number information if he/she did set the '$locationSelectorName' to 'add'
  663. {
  664. if ($callNumberName == "") // if there's no call number info provided by the admin...
  665. $callNumberName = $callNumberPrefix . " @ "; // ...insert the admin's call number prefix
  666. elseif (!preg_match("/@/", $callNumberName)) // if there's a call number provided by the admin that does NOT contain any '@' already...
  667. $callNumberName = $callNumberPrefix . " @ " . $callNumberName; // ...then we assume the admin entered a personal refernce ID for this record which should be prefixed with his/her call number prefix
  668. // the contents of the 'call_number' field do contain the '@' character, i.e. we assume one or more full call numbers to be present
  669. elseif (!preg_match("/$callNumberPrefix/", $callNumberName)) // if the admin's call number prefix does NOT already occur within the contents of the 'call_number' field...
  670. {
  671. if (preg_match("/; *[^ @;][^@;]*$/", $callNumberName)) // for the admin we offer autocompletion of the call number prefix if he/she just enters his/her reference ID after the last full call number (separated by '; ')
  672. // e.g., the string 'IP� @ mschmid @ 123; 1778' will be autocompleted to 'IP� @ mschmid @ 123; IP� @ msteffens @ 1778' (with 'msteffens' being the admin user)
  673. $callNumberName = preg_replace("/^(.+); *([^@;]+)$/i", "\\1; $callNumberPrefix @ \\2", $callNumberName); // insert the admin's call number prefix before any reference ID that stand's at the end of the string of call numbers
  674. else
  675. $callNumberName = $callNumberName . "; " . $callNumberPrefix . " @ "; // ...append the admin's call number prefix to any existing call numbers
  676. }
  677. }
  678. // otherwise we simply use the information as entered by the admin
  679. if ($locationSelectorName == "remove") // remove the current user's call number from the 'call_number' field:
  680. {
  681. $callNumberName = preg_replace("/^ *$callNumberPrefix *@ *[^@;]*; */i", "", $callNumberName); // the user's call number is listed at the very beginning of the 'call_number' field
  682. $callNumberName = preg_replace("/ *; *$callNumberPrefix *@ *[^@;]*/i", "", $callNumberName); // the user's call number occurs after some other call number within the 'call_number' field
  683. $callNumberName = preg_replace("/^ *$callNumberPrefix *@ *[^@;]*$/i", "", $callNumberName); // the user's call number is the only one listed within the 'call_number' field
  684. }
  685. // handle file uploads:
  686. if (preg_match("/^(edit|delet)$/", $recordAction)) // we exclude '$recordAction = "add"' here, since file name generation needs to be done *after* the record has been created and a serial number is available
  687. {
  688. if (!empty($uploadFile) && !empty($uploadFile["tmp_name"])) // if there was a file uploaded successfully
  689. // process information of any file that was uploaded, auto-generate a file name if required and move the file to the appropriate directory:
  690. $fileName = handleFileUploads($uploadFile, $formVars);
  691. }
  692. // check if we need to set the 'contribution_id' field:
  693. // (we'll make use of the session variable '$abbrevInstitution' here)
  694. if ($contributionIDCheckBox == "1") // the user want's to add this record to the list of publications that were published by a member of his institution
  695. {
  696. if (!empty($contributionID)) // if the 'contribution_id' field is NOT empty...
  697. {
  698. if (!preg_match("/$abbrevInstitution/", $contributionID)) // ...and the current user's 'abbrev_institution' value isn't listed already within the 'contribution_id' field
  699. $contributionID = $contributionID . "; " . $abbrevInstitution; // append the user's 'abbrev_institution' value to the end of the 'contribution_id' field
  700. }
  701. else // the 'contribution_id' field is empty
  702. $contributionID = $abbrevInstitution; // insert the current user's 'abbrev_institution' value
  703. }
  704. else // if present, remove the current user's abbreviated institution name from the 'contribution_id' field:
  705. {
  706. if (preg_match("/$abbrevInstitution/", $contributionID)) // if the current user's 'abbrev_institution' value is listed within the 'contribution_id' field, we'll remove it:
  707. {
  708. $contributionID = preg_replace("/^ *$abbrevInstitution *[^;]*; */i", "", $contributionID); // the user's abbreviated institution name is listed at the very beginning of the 'contribution_id' field
  709. $contributionID = preg_replace("/ *; *$abbrevInstitution *[^;]*/i", "", $contributionID); // the user's abbreviated institution name occurs after some other institutional abbreviation within the 'contribution_id' field
  710. $contributionID = preg_replace("/^ *$abbrevInstitution *[^;]*$/i", "", $contributionID); // the user's abbreviated institution name is the only one listed within the 'contribution_id' field
  711. }
  712. }
  713. // check if we need to set the 'online_publication' field:
  714. if ($onlinePublicationCheckBox == "1") // the user did mark the "Online publication" checkbox
  715. $onlinePublication = "yes";
  716. else
  717. $onlinePublication = "no";
  718. // remove any meaningless delimiter(s) from the beginning or end of a field string:
  719. // Note: - this cleanup is only done for fields that may contain sub-elements, which are the fields:
  720. // 'author', 'keywords', 'place', 'language', 'summary_language', 'area', 'user_keys' and 'user_groups'
  721. // - currently, only the semicolon (optionally surrounded by whitespace) is supported as sub-element delimiter
  722. $authorName = trimTextPattern($authorName, "( *; *)+", true, true); // function 'trimTextPattern()' is defined in 'include.inc.php'
  723. $keywordsName = trimTextPattern($keywordsName, "( *; *)+", true, true);
  724. $placeName = trimTextPattern($placeName, "( *; *)+", true, true);
  725. $languageName = trimTextPattern($languageName, "( *; *)+", true, true);
  726. $summaryLanguageName = trimTextPattern($summaryLanguageName, "( *; *)+", true, true);
  727. $areaName = trimTextPattern($areaName, "( *; *)+", true, true);
  728. $userKeysName = trimTextPattern($userKeysName, "( *; *)+", true, true);
  729. $userGroupsName = trimTextPattern($userGroupsName, "( *; *)+", true, true);
  730. $queryDeleted = ""; // initialize the '$queryDeleted' variable in order to prevent 'Undefined variable...' messages
  731. // Is this an update?
  732. if ($recordAction == "edit") // alternative method to check for an 'edit' action: if (preg_match("/^[0-9]+$/",$serialNo)) // a valid serial number must be an integer
  733. // yes, the form already contains a valid serial number, so we'll have to update the relevant record:
  734. {
  735. // UPDATE - construct queries to update the relevant record
  736. $queryRefs = "UPDATE $tableRefs SET "
  737. . "author = " . quote_smart($authorName) . ", "
  738. . "first_author = " . quote_smart($firstAuthor) . ", "
  739. . "author_count = " . quote_smart($authorCount) . ", "
  740. . "title = " . quote_smart($titleName) . ", "
  741. . "year = " . quote_smart($yearNo) . ", "
  742. . "publication = " . quote_smart($publicationName) . ", "
  743. . "abbrev_journal = " . quote_smart($abbrevJournalName) . ", "
  744. . "volume = " . quote_smart($volumeNo) . ", "
  745. . "volume_numeric = " . quote_smart($volumeNumericNo) . ", "
  746. . "issue = " . quote_smart($issueNo) . ", "
  747. . "pages = " . quote_smart($pagesNo) . ", "
  748. . "first_page = " . quote_smart($firstPage) . ", "
  749. . "address = " . quote_smart($addressName) . ", "
  750. . "corporate_author = " . quote_smart($corporateAuthorName) . ", "
  751. . "keywords = " . quote_smart($keywordsName) . ", "
  752. . "abstract = " . quote_smart($abstractName) . ", "
  753. . "publisher = " . quote_smart($publisherName) . ", "
  754. . "place = " . quote_smart($placeName) . ", "
  755. . "editor = " . quote_smart($editorName) . ", "
  756. . "language = " . quote_smart($languageName) . ", "
  757. . "summary_language = " . quote_smart($summaryLanguageName) . ", "
  758. . "orig_title = " . quote_smart($origTitleName) . ", "
  759. . "series_editor = " . quote_smart($seriesEditorName) . ", "
  760. . "series_title = " . quote_smart($seriesTitleName) . ", "
  761. . "abbrev_series_title = " . quote_smart($abbrevSeriesTitleName) . ", "
  762. . "series_volume = " . quote_smart($seriesVolumeNo) . ", "
  763. . "series_volume_numeric = " . quote_smart($seriesVolumeNumericNo) . ", "
  764. . "series_issue = " . quote_smart($seriesIssueNo) . ", "
  765. . "edition = " . quote_smart($editionNo) . ", "
  766. . "issn = " . quote_smart($issnName) . ", "
  767. . "isbn = " . quote_smart($isbnName) . ", "
  768. . "medium = " . quote_smart($mediumName) . ", "
  769. . "area = " . quote_smart($areaName) . ", "
  770. . "expedition = " . quote_smart($expeditionName) . ", "
  771. . "conference = " . quote_smart($conferenceName) . ", "
  772. . "location = " . quote_smart($locationName) . ", "
  773. . "call_number = " . quote_smart($callNumberName) . ", "
  774. . "approved = " . quote_smart($approvedRadio) . ", "
  775. . "file = " . quote_smart($fileName) . ", "
  776. . "type = " . quote_smart($typeName) . ", "
  777. . "thesis = " . quote_smart($thesisName) . ", "
  778. . "notes = " . quote_smart($notesName) . ", "
  779. . "url = " . quote_smart($urlName) . ", "
  780. . "doi = " . quote_smart($doiName) . ", "
  781. . "contribution_id = " . quote_smart($contributionID) . ", "
  782. . "online_publication = " . quote_smart($onlinePublication) . ", "
  783. . "online_citation = " . quote_smart($onlineCitationName) . ", "
  784. . "modified_date = " . quote_smart($currentDate) . ", "
  785. . "modified_time = " . quote_smart($currentTime) . ", "
  786. . "modified_by = " . quote_smart($currentUser) . " "
  787. . "WHERE serial = " . quote_smart($serialNo);
  788. // first, we need to check if there's already an entry for the current record & user within the 'user_data' table:
  789. // CONSTRUCT SQL QUERY:
  790. $query = "SELECT data_id FROM $tableUserData WHERE record_id = " . quote_smart($serialNo) . " AND user_id = " . quote_smart($loginUserID); // '$loginUserID' is provided as session variable
  791. // (3) RUN the query on the database through the connection:
  792. $result = queryMySQLDatabase($query); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  793. if (mysqli_num_rows($result) == 1) // if there's already an existing user_data entry, we perform an UPDATE action:
  794. $queryUserData = "UPDATE $tableUserData SET "
  795. . "marked = " . quote_smart($markedRadio) . ", "
  796. . "copy = " . quote_smart($copyName) . ", "
  797. . "selected = " . quote_smart($selectedRadio) . ", "
  798. . "user_keys = " . quote_smart($userKeysName) . ", "
  799. . "user_notes = " . quote_smart($userNotesName) . ", "
  800. . "user_file = " . quote_smart($userFileName) . ", "
  801. . "user_groups = " . quote_smart($userGroupsName) . ", "
  802. . "cite_key = " . quote_smart($citeKeyName) . ", "
  803. . "related = " . quote_smart($relatedName) . " "
  804. . "WHERE record_id = " . quote_smart($serialNo) . " AND user_id = " . quote_smart($loginUserID); // '$loginUserID' is provided as session variable
  805. else // otherwise we perform an INSERT action:
  806. $queryUserData = "INSERT INTO $tableUserData SET "
  807. . "marked = " . quote_smart($markedRadio) . ", "
  808. . "copy = " . quote_smart($copyName) . ", "
  809. . "selected = " . quote_smart($selectedRadio) . ", "
  810. . "user_keys = " . quote_smart($userKeysName) . ", "
  811. . "user_notes = " . quote_smart($userNotesName) . ", "
  812. . "user_file = " . quote_smart($userFileName) . ", "
  813. . "user_groups = " . quote_smart($userGroupsName) . ", "
  814. . "cite_key = " . quote_smart($citeKeyName) . ", "
  815. . "related = " . quote_smart($relatedName) . ", "
  816. . "record_id = " . quote_smart($serialNo) . ", "
  817. . "user_id = " . quote_smart($loginUserID) . ", " // '$loginUserID' is provided as session variable
  818. . "data_id = NULL"; // inserting 'NULL' into an auto_increment PRIMARY KEY attribute allocates the next available key value
  819. }
  820. elseif ($recordAction == "delet") // (Note that if you delete the mother record within the 'refs' table, the corresponding child entry within the 'user_data' table will remain!)
  821. {
  822. // Instead of deleting data, deleted records will be moved to the "deleted" table. Data will be stored within the "deleted" table
  823. // until they are removed manually. This is to provide the admin with a simple recovery method in case a user did delete some data by accident...
  824. // INSERT - construct queries to add data as new record
  825. $queryDeleted = "INSERT INTO $tableDeleted SET "
  826. . "author = " . quote_smart($authorName) . ", "
  827. . "first_author = " . quote_smart($firstAuthor) . ", "
  828. . "author_count = " . quote_smart($authorCount) . ", "
  829. . "title = " . quote_smart($titleName) . ", "
  830. . "year = " . quote_smart($yearNo) . ", "
  831. . "publication = " . quote_smart($publicationName) . ", "
  832. . "abbrev_journal = " . quote_smart($abbrevJournalName) . ", "
  833. . "volume = " . quote_smart($volumeNo) . ", "
  834. . "volume_numeric = " . quote_smart($volumeNumericNo) . ", "
  835. . "issue = " . quote_smart($issueNo) . ", "
  836. . "pages = " . quote_smart($pagesNo) . ", "
  837. . "first_page = " . quote_smart($firstPage) . ", "
  838. . "address = " . quote_smart($addressName) . ", "
  839. . "corporate_author = " . quote_smart($corporateAuthorName) . ", "
  840. . "keywords = " . quote_smart($keywordsName) . ", "
  841. . "abstract = " . quote_smart($abstractName) . ", "
  842. . "publisher = " . quote_smart($publisherName) . ", "
  843. . "place = " . quote_smart($placeName) . ", "
  844. . "editor = " . quote_smart($editorName) . ", "
  845. . "language = " . quote_smart($languageName) . ", "
  846. . "summary_language = " . quote_smart($summaryLanguageName) . ", "
  847. . "orig_title = " . quote_smart($origTitleName) . ", "
  848. . "series_editor = " . quote_smart($seriesEditorName) . ", "
  849. . "series_title = " . quote_smart($seriesTitleName) . ", "
  850. . "abbrev_series_title = " . quote_smart($abbrevSeriesTitleName) . ", "
  851. . "series_volume = " . quote_smart($seriesVolumeNo) . ", "
  852. . "series_volume_numeric = " . quote_smart($seriesVolumeNumericNo) . ", "
  853. . "series_issue = " . quote_smart($seriesIssueNo) . ", "
  854. . "edition = " . quote_smart($editionNo) . ", "
  855. . "issn = " . quote_smart($issnName) . ", "
  856. . "isbn = " . quote_smart($isbnName) . ", "
  857. . "medium = " . quote_smart($mediumName) . ", "
  858. . "area = " . quote_smart($areaName) . ", "
  859. . "expedition = " . quote_smart($expeditionName) . ", "
  860. . "conference = " . quote_smart($conferenceName) . ", "
  861. . "location = " . quote_smart($locationName) . ", "
  862. . "call_number = " . quote_smart($callNumberName) . ", "
  863. . "approved = " . quote_smart($approvedRadio) . ", "
  864. . "file = " . quote_smart($fileName) . ", "
  865. . "serial = " . quote_smart($serialNo) . ", " // it's important to keep the old PRIMARY KEY (since user specific data may be still associated with this record id)
  866. . "type = " . quote_smart($typeName) . ", "
  867. . "thesis = " . quote_smart($thesisName) . ", "
  868. . "notes = " . quote_smart($notesName) . ", "
  869. . "url = " . quote_smart($urlName) . ", "
  870. . "doi = " . quote_smart($doiName) . ", "
  871. . "contribution_id = " . quote_smart($contributionID) . ", "
  872. . "online_publication = " . quote_smart($onlinePublication) . ", "
  873. . "online_citation = " . quote_smart($onlineCitationName) . ", "
  874. . "created_date = " . quote_smart($createdDate) . ", "
  875. . "created_time = " . quote_smart($createdTime) . ", "
  876. . "created_by = " . quote_smart($createdBy) . ", "
  877. . "modified_date = " . quote_smart($modifiedDate) . ", "
  878. . "modified_time = " . quote_smart($modifiedTime) . ", "
  879. . "modified_by = " . quote_smart($modifiedBy) . ", "
  880. . "orig_record = " . quote_smart($origRecord) . ", "
  881. . "deleted_date = " . quote_smart($currentDate) . ", " // store information about when and by whom this record was deleted...
  882. . "deleted_time = " . quote_smart($currentTime) . ", "
  883. . "deleted_by = " . quote_smart($currentUser);
  884. // since data have been moved from table 'refs' to table 'deleted', its now safe to delete the data from table 'refs':
  885. $queryRefs = "DELETE FROM $tableRefs WHERE serial = " . quote_smart($serialNo);
  886. }
  887. else // if the form does NOT contain a valid serial number, we'll have to add the data:
  888. {
  889. // INSERT - construct queries to add data as new record
  890. $queryRefs = "INSERT INTO $tableRefs SET "
  891. . "author = " . quote_smart($authorName) . ", "
  892. . "first_author = " . quote_smart($firstAuthor) . ", "
  893. . "author_count = " . quote_smart($authorCount) . ", "
  894. . "title = " . quote_smart($titleName) . ", "
  895. . "year = " . quote_smart($yearNo) . ", "
  896. . "publication = " . quote_smart($publicationName) . ", "
  897. . "abbrev_journal = " . quote_smart($abbrevJournalName) . ", "
  898. . "volume = " . quote_smart($volumeNo) . ", "
  899. . "volume_numeric = " . quote_smart($volumeNumericNo) . ", "
  900. . "issue = " . quote_smart($issueNo) . ", "
  901. . "pages = " . quote_smart($pagesNo) . ", "
  902. . "first_page = " . quote_smart($firstPage) . ", "
  903. . "address = " . quote_smart($addressName) . ", "
  904. . "corporate_author = " . quote_smart($corporateAuthorName) . ", "
  905. . "keywords = " . quote_smart($keywordsName) . ", "
  906. . "abstract = " . quote_smart($abstractName) . ", "
  907. . "publisher = " . quote_smart($publisherName) . ", "
  908. . "place = " . quote_smart($placeName) . ", "
  909. . "editor = " . quote_smart($editorName) . ", "
  910. . "language = " . quote_smart($languageName) . ", "
  911. . "summary_language = " . quote_smart($summaryLanguageName) . ", "
  912. . "orig_title = " . quote_smart($origTitleName) . ", "
  913. . "series_editor = " . quote_smart($seriesEditorName) . ", "
  914. . "series_title = " . quote_smart($seriesTitleName) . ", "
  915. . "abbrev_series_title = " . quote_smart($abbrevSeriesTitleName) . ", "
  916. . "series_volume = " . quote_smart($seriesVolumeNo) . ", "
  917. . "series_volume_numeric = " . quote_smart($seriesVolumeNumericNo) . ", "
  918. . "series_issue = " . quote_smart($seriesIssueNo) . ", "
  919. . "edition = " . quote_smart($editionNo) . ", "
  920. . "issn = " . quote_smart($issnName) . ", "
  921. . "isbn = " . quote_smart($isbnName) . ", "
  922. . "medium = " . quote_smart($mediumName) . ", "
  923. . "area = " . quote_smart($areaName) . ", "
  924. . "expedition = " . quote_smart($expeditionName) . ", "
  925. . "conference = " . quote_smart($conferenceName) . ", "
  926. . "location = " . quote_smart($locationName) . ", "
  927. . "call_number = " . quote_smart($callNumberName) . ", "
  928. . "approved = " . quote_smart($approvedRadio) . ", "
  929. . "file = " . quote_smart($fileName) . ", " // for new records the 'file' field will be updated once more after record creation, since the serial number of the newly created record may be required when generating a file name for any uploaded file
  930. . "serial = NULL, " // inserting 'NULL' into an auto_increment PRIMARY KEY attribute allocates the next available key value
  931. . "type = " . quote_smart($typeName) . ", "
  932. . "thesis = " . quote_smart($thesisName) . ", "
  933. . "notes = " . quote_smart($notesName) . ", "
  934. . "url = " . quote_smart($urlName) . ", "
  935. . "doi = " . quote_smart($doiName) . ", "
  936. . "contribution_id = " . quote_smart($contributionID) . ", "
  937. . "online_publication = " . quote_smart($onlinePublication) . ", "
  938. . "online_citation = " . quote_smart($onlineCitationName) . ", "
  939. . "created_date = " . quote_smart($currentDate) . ", "
  940. . "created_time = " . quote_smart($currentTime) . ", "
  941. . "created_by = " . quote_smart($currentUser) . ", "
  942. . "modified_date = " . quote_smart($currentDate) . ", "
  943. . "modified_time = " . quote_smart($currentTime) . ", "
  944. . "modified_by = " . quote_smart($currentUser);
  945. // '$queryUserData' will be set up after '$queryRefs' has been conducted (see below), since the serial number of the newly created 'refs' record is required for the '$queryUserData' query
  946. }
  947. // Apply some clean-up to the SQL query:
  948. // - if a field of type=NUMBER is empty, we set it back to NULL (otherwise the empty string would be converted to "0")
  949. // - if the 'thesis' field is empty, we also set it back to NULL (this ensures correct sorting when outputting citations with '$citeOrder="type"' or '$citeOrder="type-year"')
  950. if (preg_match("/(year|volume_numeric|first_page|series_volume_numeric|edition|orig_record|thesis) = [\"']0?[\"']/", $queryRefs))
  951. $queryRefs = preg_replace("/(year|volume_numeric|first_page|series_volume_numeric|edition|orig_record|thesis) = [\"']0?[\"']/", "\\1 = NULL", $queryRefs);
  952. if (preg_match("/(year|volume_numeric|first_page|series_volume_numeric|edition|orig_record|thesis) = [\"']0?[\"']/", $queryDeleted))
  953. $queryDeleted = preg_replace("/(year|volume_numeric|first_page|series_volume_numeric|edition|orig_record|thesis) = [\"']0?[\"']/", "\\1 = NULL", $queryDeleted);
  954. // --------------------------------------------------------------------
  955. // (3) RUN QUERY, (4) DISPLAY HEADER & RESULTS
  956. // (3) RUN the query on the database through the connection:
  957. if ($recordAction == "edit")
  958. {
  959. $result = queryMySQLDatabase($queryRefs); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  960. $result = queryMySQLDatabase($queryUserData); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  961. getUserGroups($tableUserData, $loginUserID); // update the 'userGroups' session variable (function 'getUserGroups()' is defined in 'include.inc.php')
  962. }
  963. elseif ($recordAction == "add")
  964. {
  965. $result = queryMySQLDatabase($queryRefs); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  966. // Get the record id that was created
  967. $serialNo = @ mysqli_insert_id($connection); // find out the unique ID number of the newly created record (Note: this function should be called immediately after the
  968. // SQL INSERT statement! After any subsequent query it won't be possible to retrieve the auto_increment identifier value for THIS record!)
  969. $formVars['serialNo'] = $serialNo; // for '$recordAction = "add"' we update the original '$formVars' array element to ensure a correct serial number when generating the file name via the 'parsePlaceholderString()' function
  970. // handle file uploads:
  971. // for '$recordAction = "add"' file name generation needs to be done *after* the record has been created and a serial number is available
  972. if (!empty($uploadFile) && !empty($uploadFile["tmp_name"])) // if there was a file uploaded successfully
  973. {
  974. // process information of any file that was uploaded, auto-generate a file name if required and move the file to the appropriate directory:
  975. $fileName = handleFileUploads($uploadFile, $formVars);
  976. $queryRefsUpdateFileName = "UPDATE $tableRefs SET file = " . quote_smart($fileName) . " WHERE serial = " . quote_smart($serialNo);
  977. $result = queryMySQLDatabase($queryRefsUpdateFileName); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  978. }
  979. $queryUserData = "INSERT INTO $tableUserData SET "
  980. . "marked = " . quote_smart($markedRadio) . ", "
  981. . "copy = " . quote_smart($copyName) . ", "
  982. . "selected = " . quote_smart($selectedRadio) . ", "
  983. . "user_keys = " . quote_smart($userKeysName) . ", "
  984. . "user_notes = " . quote_smart($userNotesName) . ", "
  985. . "user_file = " . quote_smart($userFileName) . ", "
  986. . "user_groups = " . quote_smart($userGroupsName) . ", "
  987. . "cite_key = " . quote_smart($citeKeyName) . ", "
  988. . "related = " . quote_smart($relatedName) . ", "
  989. . "record_id = " . quote_smart($serialNo) . ", "
  990. . "user_id = " . quote_smart($loginUserID) . ", " // '$loginUserID' is provided as session variable
  991. . "data_id = NULL"; // inserting 'NULL' into an auto_increment PRIMARY KEY attribute allocates the next available key value
  992. $result = queryMySQLDatabase($queryUserData); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  993. getUserGroups($tableUserData, $loginUserID); // update the 'userGroups' session variable (function 'getUserGroups()' is defined in 'include.inc.php')
  994. // Send EMAIL announcement:
  995. if ($sendEmailAnnouncements == "yes") // ('$sendEmailAnnouncements' is specified in 'ini.inc.php')
  996. {
  997. // first, build an appropriate author string:
  998. // Call the 'extractAuthorsLastName()' function (defined in 'include.inc.php') to extract the last name of a particular author (specified by position). Required Parameters:
  999. // 1. pattern describing delimiter that separates different authors
  1000. // 2. pattern describing delimiter that separates author name & initials (within one author)
  1001. // 3. position of the author whose last name shall be extracted (e.g., "1" will return the 1st author's last name)
  1002. // 4. contents of the author field
  1003. $authorString = extractAuthorsLastName("/ *; */", // get last name of first author
  1004. "/ *, */",
  1005. 1,
  1006. $authorName);
  1007. if ($authorCount == "2") // two authors
  1008. {
  1009. $authorString .= " & ";
  1010. $authorString .= extractAuthorsLastName("/ *; */", // get last name of second author
  1011. "/ *, */",
  1012. 2,
  1013. $authorName);
  1014. }
  1015. if ($authorCount == "3") // at least three authors
  1016. $authorString .= " et al";
  1017. // send a notification email to the mailing list email address '$mailingListEmail' (specified in 'ini.inc.php'):
  1018. $emailRecipient = "Literature Database Announcement List <" . $mailingListEmail . ">";
  1019. $emailSubject = "New entry: " . $authorString . " " . $yearNo;
  1020. if (!empty($publicationName))
  1021. {
  1022. $emailSubject .= " (" . $publicationName;
  1023. if (!empty($volumeNo))
  1024. $emailSubject .= " " . $volumeNo . ")";
  1025. else
  1026. $emailSubject .= ")";
  1027. }
  1028. $emailBody = "The following record has been added to the " . $officialDatabaseName . ":"
  1029. . "\n\n author: " . $authorName
  1030. . "\n title: " . $titleName
  1031. . "\n year: " . $yearNo
  1032. . "\n publication: " . $publicationName
  1033. . "\n volume: " . $volumeNo
  1034. . "\n issue: " . $issueNo
  1035. . "\n pages: " . $pagesNo
  1036. . "\n\n added by: " . $loginFirstName . " " . $loginLastName
  1037. . "\n details: " . $databaseBaseURL . "show.php?record=" . $serialNo // ('$databaseBaseURL' is specified in 'ini.inc.php')
  1038. . "\n";
  1039. sendEmail($emailRecipient, $emailSubject, $emailBody);
  1040. }
  1041. }
  1042. else // '$recordAction' is "delet" (Note that if you delete the mother record within the 'refs' table, the corresponding child entry within the 'user_data' table will remain!)
  1043. {
  1044. $result = queryMySQLDatabase($queryDeleted); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  1045. $result = queryMySQLDatabase($queryRefs); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  1046. }
  1047. // Build correct header message:
  1048. $headerMsg = "The record no. " . $serialNo . " has been successfully " . $recordAction . "ed.";
  1049. // Append a "Display previous search results" link to the feedback header message if it will be displayed above a single record that was added/edited last:
  1050. if (!empty($oldMultiRecordQuery))
  1051. {
  1052. // Remove any previous 'headerMsg' parameter from the saved query URL:
  1053. unset($oldMultiRecordQuery["headerMsg"]);
  1054. // After a record has been successfully added/edited/deleted, we include a link to the last multi-record query in the feedback header message if:
  1055. // 1) the SQL query in 'oldQuery' is different from that one stored in 'oldMultiRecordQuery', i.e. if 'oldQuery' points to a single record -OR-
  1056. // 2) one or more new records have been added/imported
  1057. if ((!empty($oldQuery) AND ($oldQuery["sqlQuery"] != $oldMultiRecordQuery["sqlQuery"]) AND ($recordAction != "delet")) OR ($recordAction == "add"))
  1058. {
  1059. // Generate a 'search.php' URL that points to the last multi-record query:
  1060. $oldMultiRecordQueryURL = generateURL("search.php", "html", $oldMultiRecordQuery, true); // function 'generateURL()' is defined in 'include.inc.php'
  1061. // Append a link to the previous search results to the feedback header message:
  1062. $headerMsg .= " <a href=\"" . $oldMultiRecordQueryURL . "\">Display previous search results</a>.";
  1063. }
  1064. }
  1065. // Save the header message to a session variable:
  1066. // NOTE: Opposed to single-record feedback (or the 'receipt.php' feedback), we don't include the header message within the 'headerMsg' URL parameter when
  1067. // displaying the message above the last multi-record query. If we save the header message to a session variable ("HeaderString") this causes the
  1068. // receiving script ("search.php") to display it just once; if we'd instead include the header message within the 'headerMsg' parameter, it would
  1069. // be displayed above results of the last multi-record query even when the user browses to another search results page or changes the sort order.
  1070. $HeaderString = returnMsg($headerMsg, "", "", "HeaderString"); // function 'returnMsg()' is defined in 'include.inc.php'
  1071. if ($recordAction == "add")
  1072. {
  1073. // Display the newly added record:
  1074. header("Location: show.php?record=" . $serialNo . "&headerMsg=" . rawurlencode($headerMsg));
  1075. }
  1076. elseif (($recordAction == "delet") AND !empty($oldMultiRecordQuery))
  1077. {
  1078. // Generate a 'search.php' URL that points to the last multi-record query:
  1079. $oldMultiRecordQueryURL = generateURL("search.php", "html", $oldMultiRecordQuery, false);
  1080. // Display the previous search results:
  1081. header("Location: $oldMultiRecordQueryURL");
  1082. }
  1083. elseif (($recordAction != "delet") AND !empty($oldQuery))
  1084. {
  1085. // Remove any previous 'headerMsg' parameter from the saved query URL:
  1086. unset($oldQuery["headerMsg"]);
  1087. // Generate a 'search.php' URL that points to the formerly displayed results page:
  1088. $queryURL = generateURL("search.php", "html", $oldQuery, false);
  1089. // Route back to the previous results display:
  1090. // (i.e., after submission of the edit mask, we now go straight back to the results list that was displayed previously,
  1091. // no matter what display type it was (List view, Citation view, or Details view))
  1092. header("Location: $queryURL");
  1093. }
  1094. else // old method that uses 'receipt.php' for feedback:
  1095. {
  1096. // (4) Call 'receipt.php' which displays links to the modifyed/added record as well as to the previous search results page (if any)
  1097. // (routing feedback output to a different script page will avoid any reload problems effectively!)
  1098. header("Location: receipt.php?recordAction=" . $recordAction . "&serialNo=" . $serialNo . "&headerMsg=" . rawurlencode($headerMsg));
  1099. }
  1100. // --------------------------------------------------------------------
  1101. // (5) CLOSE CONNECTION
  1102. // (5) CLOSE the database connection:
  1103. disconnectFromMySQLDatabase(); // function 'disconnectFromMySQLDatabase()' is defined in 'include.inc.php'
  1104. // --------------------------------------------------------------------
  1105. // Handle file uploads:
  1106. // process information of any file that was uploaded, auto-generate a file name if required
  1107. // and move the file to the appropriate directory
  1108. function handleFileUploads($uploadFile, $formVars)
  1109. {
  1110. global $filesBaseDir; // these variables are defined in 'ini.inc.php'
  1111. global $moveFilesIntoSubDirectories;
  1112. global $dirNamingScheme;
  1113. global $renameUploadedFiles;
  1114. global $fileNamingScheme;
  1115. global $handleNonASCIIChars;
  1116. global $allowedFileNameCharacters;
  1117. global $allowedDirNameCharacters;
  1118. global $changeCaseInFileNames;
  1119. global $changeCaseInDirNames;
  1120. $tmpFilePath = $uploadFile["tmp_name"];
  1121. // Generate file name:
  1122. if ($renameUploadedFiles == "yes") // rename file according to a standard naming scheme
  1123. {
  1124. if (preg_match("/.+\.[^.]+$/i", $uploadFile["name"])) // preserve any existing file name extension
  1125. $fileNameExtension = preg_replace("/.+(\.[^.]+)$/i", "\\1", $uploadFile["name"]);
  1126. else
  1127. $fileNameExtension = "";
  1128. // auto-generate a file name according to the naming scheme given in '$fileNamingScheme':
  1129. $newFileName = parsePlaceholderString($formVars, $fileNamingScheme, "<:serial:>"); // function 'parsePlaceholderString()' is defined in 'include.inc.php'
  1130. // handle non-ASCII and unwanted characters:
  1131. $newFileName = handleNonASCIIAndUnwantedCharacters($newFileName, $allowedFileNameCharacters, $handleNonASCIIChars); // function 'handleNonASCIIAndUnwantedCharacters()' is defined in 'include.inc.php'
  1132. // add original file name extension:
  1133. $newFileName .= $fileNameExtension;
  1134. }
  1135. else // take the file name as given by the user:
  1136. $newFileName = $uploadFile["name"];
  1137. // Generate directory structure:
  1138. if ($moveFilesIntoSubDirectories != "never")
  1139. {
  1140. // remove any slashes (i.e., directory delimiter(s)) from the beginning or end of '$dirNamingScheme':
  1141. $dirNamingScheme = trimTextPattern($dirNamingScheme, "[\/\\\\]+", true, true); // function 'trimTextPattern()' is defined in 'include.inc.php'
  1142. $dirNamingSchemePartsArray = preg_split("#[/\\\\]+#", $dirNamingScheme); // split on slashes to separate between multiple sub-directories
  1143. $subDirNamesArray = array(); // initialize array variable which will hold the generated sub-directory names
  1144. // auto-generate a directory name according to the naming scheme given in '$dirNamingScheme'
  1145. // and handle non-ASCII chars plus unwanted characters:
  1146. foreach($dirNamingSchemePartsArray as $dirNamingSchemePart)
  1147. {
  1148. // parse given placeholder string:
  1149. $subDirName = parsePlaceholderString($formVars, $dirNamingSchemePart, ""); // function 'parsePlaceholderString()' is defined in 'include.inc.php'
  1150. // handle non-ASCII and unwanted characters:
  1151. $subDirName = handleNonASCIIAndUnwantedCharacters($subDirName, $allowedDirNameCharacters, $handleNonASCIIChars); // function 'handleNonASCIIAndUnwantedCharacters()' is defined in 'include.inc.php'
  1152. if (!empty($subDirName))
  1153. $subDirNamesArray[] = $subDirName;
  1154. }
  1155. if (!empty($subDirNamesArray))
  1156. $subDirName = implode("/", $subDirNamesArray) . "/"; // merge any individual sub-directory names and append a slash to generate final sub-directory structure
  1157. else
  1158. $subDirName = "";
  1159. }
  1160. else
  1161. $subDirName = "";
  1162. // Perform any case transformations:
  1163. // change case of file name:
  1164. if (preg_match("/^(lower|upper)$/i", $changeCaseInFileNames))
  1165. $newFileName = changeCase($changeCaseInFileNames, $newFileName); // function 'changeCase()' is defined in 'include.inc.php'
  1166. // change case of DIR name:
  1167. if (preg_match("/^(lower|upper)$/i", $changeCaseInDirNames) && !empty($subDirName))
  1168. $subDirName = changeCase($changeCaseInDirNames, $subDirName);
  1169. // Generate full destination path:
  1170. // - if '$moveFilesIntoSubDirectories = "existing"' and there's an existing sub-directory (within the default files directory '$filesBaseDir')
  1171. // whose name equals '$subDirName' we'll copy the new file into that sub-directory
  1172. // - if '$moveFilesIntoSubDirectories = "always"' and '$subDirName' isn't empty, we'll generate an appropriately named sub-directory if it
  1173. // doesn't exist yet
  1174. // - otherwise we just copy the file to the root-level of '$filesBaseDir':
  1175. if (!empty($subDirName) && (($moveFilesIntoSubDirectories == "existing" AND is_dir($filesBaseDir . $subDirName)) OR ($moveFilesIntoSubDirectories == "always")))
  1176. {
  1177. $destFilePath = $filesBaseDir . $subDirName . $newFileName; // new file will be copied into sub-directory within '$filesBaseDir'...
  1178. // copy the new subdir name & file name to the 'file' field variable:
  1179. // 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
  1180. // from the files directory! Automatic file removal is omitted on purpose since it's way more difficult to recover an
  1181. // inadvertently deleted file than to delete it manually. However, future versions should introduce a smarter way of handling
  1182. // orphaned files...
  1183. $fileName = $subDirName . $newFileName;
  1184. if ($moveFilesIntoSubDirectories == "always" AND !is_dir($filesBaseDir . $subDirName))
  1185. // make sure the directory we're moving the file to exists before proceeding:
  1186. recursiveMkdir($filesBaseDir . $subDirName);
  1187. }
  1188. else
  1189. {
  1190. $destFilePath = $filesBaseDir . $newFileName; // new file will be copied to root-level of '$filesBaseDir'...
  1191. $fileName = $newFileName; // copy the new file name to the 'file' field variable (see note above!)
  1192. }
  1193. // Copy uploaded file from temporary location to the default file directory specified in '$filesBaseDir':
  1194. // (for more on PHP file uploads see <http://www.php.net/manual/en/features.file-upload.php>)
  1195. move_uploaded_file($tmpFilePath, $destFilePath);
  1196. return $fileName;
  1197. }
  1198. // --------------------------------------------------------------------
  1199. // recursively create directories:
  1200. // this function creates the specified directory using mkdir()
  1201. // (adopted from user-contributed function at <http://de2.php.net/manual/en/function.mkdir.php>)
  1202. function recursiveMkdir($path)
  1203. {
  1204. if (!is_dir($path)) // the directory doesn't exist
  1205. {
  1206. // recurse, passing the parent directory so that it gets created
  1207. // (note that dirname returns the parent directory of the last item of the path
  1208. // regardless of whether the last item is a directory or a file)
  1209. recursiveMkdir(dirname($path));
  1210. mkdir($path, 0770); // create directory
  1211. // alternatively, if the above line doesn't work for you, you might want to try:
  1212. // $oldumask = umask(0);
  1213. // mkdir($path, 0755); // create directory
  1214. // umask($oldumask);
  1215. }
  1216. }
  1217. // --------------------------------------------------------------------
  1218. ?>