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.

1454 lines
77 KiB

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