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.

315 lines
16 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: ./query_modify.php
  13. // Repository: $HeadURL: file:///svn/p/refbase/code/branches/bleeding-edge/query_modify.php $
  14. // Author(s): Matthias Steffens <mailto:refbase@extracts.de>
  15. //
  16. // Created: 23-May-04, 20:42
  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 user queries.
  21. // It then relocates back to the main page ('index.php') so that the user
  22. // can verify the changes.
  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. // Write the (POST) form variables into an array:
  40. foreach($_POST as $varname => $value)
  41. $formVars[$varname] = trim($value); // remove any leading or trailing whitespace from the field's contents & copy the trimmed string to the '$formVars' array
  42. // $formVars[$varname] = trim(clean($value, 50)); // the use of the clean function would be more secure!
  43. // --------------------------------------------------------------------
  44. // Extract form variables sent through POST:
  45. // Note: Although we could use the '$formVars' array directly below (e.g.: $formVars['pageLoginStatus'] etc., like in 'user_validation.php'), we'll read out
  46. // 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
  47. // may expose yet another security hole...)
  48. // First of all, check if this script was called by something else than 'query_manager.php':
  49. if (!preg_match("#/query_manager\.php#i", $referer)) // variable '$referer' is globally defined in function 'start_session()' in 'include.inc.php'
  50. {
  51. // return an appropriate error message:
  52. $HeaderString = returnMsg($loc["Warning_InvalidCallToScript"] . " '" . scriptURL() . "'!", "warning", "strong", "HeaderString"); // functions 'returnMsg()' and 'scriptURL()' are defined in 'include.inc.php'
  53. header("Location: " . $referer); // redirect to calling page
  54. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  55. }
  56. // Extract the form used by the user:
  57. $formType = $formVars['formType'];
  58. // Extract the type of action requested by the user (either 'add', 'edit', 'delet', or ''):
  59. // ('' will be treated equal to 'add')
  60. if (isset($formVars['queryAction']) AND !empty($formVars['queryAction']))
  61. $queryAction = $formVars['queryAction'];
  62. else
  63. $queryAction = "add";
  64. // Determine the button that was hit by the user (either 'Add Query', 'Edit Query', 'Delete Query' or ''):
  65. // '$submitAction' is only used to determine any 'delet' action! (where '$submitAction' = 'Delete Query')
  66. // (otherwise, only '$queryAction' controls how to proceed)
  67. $submitAction = $formVars['submit'];
  68. if ($submitAction == "Delete Query") // *delete* Query
  69. $queryAction = "delet";
  70. // get the query ID (if any) which is required when editing queries:
  71. if (isset($formVars['queryID']))
  72. $queryID = $formVars['queryID'];
  73. else
  74. $queryID = "";
  75. // Extract the type of display requested by the user (normally, either 'Display', 'Cite' or ''):
  76. // ('' will produce the default columnar output style)
  77. // Note: In contrast to other scripts, the 'displayType' parameter is not passed via the submit button but via a hidden form tag 'displayType'
  78. if (isset($formVars['displayType']))
  79. $displayType = $formVars['displayType'];
  80. else
  81. $displayType = "";
  82. // For a given display type, extract the view type requested by the user (either 'Mobile', 'Print', 'Web' or ''):
  83. // ('' will produce the default 'Web' output style)
  84. if (isset($formVars['queryViewType']))
  85. $queryViewType = $formVars['queryViewType'];
  86. else
  87. $queryViewType = "";
  88. // Extract other form values provided by 'query_manager.php':
  89. if (isset($formVars['queryName']))
  90. $queryName = $formVars['queryName'];
  91. else
  92. $queryName = "";
  93. if (isset($formVars['sqlQuery']))
  94. $sqlQuery = $formVars['sqlQuery'];
  95. else
  96. $sqlQuery = "";
  97. if (isset($formVars['showQuery']))
  98. $showQuery = $formVars['showQuery'];
  99. else
  100. $showQuery = "";
  101. if (isset($formVars['showLinks']))
  102. $showLinks = $formVars['showLinks'];
  103. else
  104. $showLinks = "";
  105. if (isset($formVars['showRows']) AND preg_match("/^[1-9]+[0-9]*$/", $formVars['showRows'])) // NOTE: we silently adjust the 'showRows' parameter if anything other than a positive integer was given
  106. $showRows = $formVars['showRows'];
  107. else
  108. $showRows = $_SESSION['userRecordsPerPage']; // get the default number of records per page preferred by the current user
  109. if (isset($formVars['citeStyle']))
  110. $citeStyle = $formVars['citeStyle']; // get the cite style chosen by the user
  111. else
  112. $citeStyle = "";
  113. if (preg_match("/%20/", $citeStyle)) // if '$citeStyle' still contains URL encoded data... ('%20' is the URL encoded form of a space, see note below!)
  114. $citeStyle = rawurldecode($citeStyle); // ...URL decode 'citeStyle' statement (it was URL encoded before incorporation into a hidden tag of the 'sqlSearch' form to avoid any HTML syntax errors)
  115. // NOTE: URL encoded data that are included within a *link* will get URL decoded automatically *before* extraction via '$_REQUEST'!
  116. // 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)!
  117. if (isset($formVars['citeOrder']))
  118. $citeOrder = $formVars['citeOrder']; // get information how the data should be sorted. If this param is set to 'Year', records will be listed in blocks sorted by year.
  119. else
  120. $citeOrder = "";
  121. if (isset($formVars['origQueryName']))
  122. $origQueryName = rawurldecode($formVars['origQueryName']); // get the original query name that was included within a hidden form tag (and since it got URL encoded, we'll need to decode it again)
  123. else
  124. $origQueryName = "";
  125. // --------------------------------------------------------------------
  126. // (1) OPEN CONNECTION, (2) SELECT DATABASE
  127. connectToMySQLDatabase(); // function 'connectToMySQLDatabase()' is defined in 'include.inc.php'
  128. // --------------------------------------------------------------------
  129. // VALIDATE data fields:
  130. // NOTE: for all fields that are validated here must exist error parsing code (of the form: " . fieldError("languageName", $errors) . ")
  131. // in front of the respective <input> form field in 'query_manager.php'! Otherwise the generated error won't be displayed!
  132. // Validate the 'Query Name' field:
  133. if (empty($queryName))
  134. $errors["queryName"] = "You must specify a name for your query:"; // 'queryName' must not be empty
  135. elseif (preg_match("/;/", $queryName))
  136. $errors["queryName"] = "Your query name cannot contain a semicolon (';')<br>since this character is used as delimiter:"; // the user's query name cannot contain a semicolon (';') since this character is used as delimiter between query names within the 'userQueries' session variable (see function 'getUserQueries()' in 'include.inc.php')
  137. if (($queryAction == "add") OR (($queryAction == "edit") AND ($queryName != $origQueryName))) // if the user did modify the query name, check if the new query name does already exist for this user:
  138. {
  139. $query = "SELECT query_id, query_name FROM $tableQueries WHERE user_id = " . quote_smart($loginUserID) . " AND query_name = " . quote_smart($queryName); // the global variable '$loginUserID' gets set in function 'start_session()' within 'include.inc.php'
  140. $result = queryMySQLDatabase($query); // RUN the query on the database through the connection (function 'queryMySQLDatabase()' is defined in 'include.inc.php')
  141. if (@ mysqli_num_rows($result) > 0) // if there's already a saved query (belonging to this user) with exactly the same name
  142. $errors["queryName"] = "You've got already a query with that name!<br>Please choose a different name:"; // the user's query name must be unique (since the query popup of the 'Recall My Query' form on the main page uses the query's name to recall a particular query)
  143. // note that we could allow for duplicate query names if the query popup on the main page would work with query IDs instead. However, from an interface design perspective, duplicate query names shouldn't be allowed anyhow. So we simply don't permit them.
  144. }
  145. // Validate the 'SQL Query' field:
  146. if (empty($sqlQuery))
  147. $errors["sqlQuery"] = "You must specify a query string:"; // 'sqlQuery' must not be empty
  148. elseif (!preg_match("/^SELECT/i", $sqlQuery))
  149. $errors["sqlQuery"] = "You can only save SELECT queries:"; // currently, the user is only allowed to save SELECT queries
  150. // --------------------------------------------------------------------
  151. // Now the script has finished the validation, check if there were any errors:
  152. if (count($errors) > 0)
  153. {
  154. // Write back session variables:
  155. saveSessionVariable("errors", $errors); // function 'saveSessionVariable()' is defined in 'include.inc.php'
  156. saveSessionVariable("formVars", $formVars);
  157. // There are errors. Relocate back to the 'Add/Edit Query' form (script 'query_manager.php'):
  158. // NOTE: we still use '$_SERVER['HTTP_REFERER']' instead of '$referer' here since, ATM, function 'showLogin()' generates a generic referrer that gets in
  159. // the way since it is saved to the 'referer' session variable (which is preferred by function 'start_session()' over '$_SERVER['HTTP_REFERER']')
  160. header("Location: " . $_SERVER['HTTP_REFERER']);
  161. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  162. }
  163. // --------------------------------------------------------------------
  164. // If we made it here, then the data is considered valid!
  165. // CONSTRUCT SQL QUERY:
  166. // Is this an update?
  167. if ($queryAction == "edit")
  168. {
  169. // UPDATE - update the relevant query
  170. $query = "UPDATE $tableQueries SET "
  171. . "query_name = " . quote_smart($queryName)
  172. . ", display_type = " . quote_smart($displayType)
  173. . ", view_type = " . quote_smart($queryViewType)
  174. . ", query = " . quote_smart($sqlQuery)
  175. . ", show_query = " . quote_smart($showQuery)
  176. . ", show_links = " . quote_smart($showLinks)
  177. . ", show_rows = " . quote_smart($showRows)
  178. . ", cite_style_selector = " . quote_smart($citeStyle)
  179. . ", cite_order = " . quote_smart($citeOrder)
  180. . " WHERE query_id = " . quote_smart($queryID);
  181. }
  182. elseif ($queryAction == "delet")
  183. {
  184. // DELETE - delete existing query
  185. $query = "DELETE FROM $tableQueries WHERE query_id = " . quote_smart($queryID);
  186. }
  187. else // add the data:
  188. {
  189. // INSERT - add new query
  190. $query = "INSERT INTO $tableQueries SET "
  191. . "user_id = " . quote_smart($loginUserID) // the global variable '$loginUserID' gets set in function 'start_session()' within 'include.inc.php'
  192. . ", query_name = " . quote_smart($queryName)
  193. . ", display_type = " . quote_smart($displayType)
  194. . ", view_type = " . quote_smart($queryViewType)
  195. . ", query = " . quote_smart($sqlQuery)
  196. . ", show_query = " . quote_smart($showQuery)
  197. . ", show_links = " . quote_smart($showLinks)
  198. . ", show_rows = " . quote_smart($showRows)
  199. . ", cite_style_selector = " . quote_smart($citeStyle)
  200. . ", cite_order = " . quote_smart($citeOrder)
  201. . ", last_execution = NOW()" // set 'last_execution' field to the current date & time in 'DATETIME' format (which is 'YYYY-MM-DD HH:MM:SS', e.g.: '2003-12-31 23:45:59')
  202. . ", query_id = NULL"; // inserting 'NULL' into an auto_increment PRIMARY KEY attribute allocates the next available key value
  203. }
  204. // --------------------------------------------------------------------
  205. // (3) RUN QUERY, (4) DISPLAY HEADER & RESULTS
  206. // (3) RUN the query on the database through the connection:
  207. $result = queryMySQLDatabase($query); // function 'queryMySQLDatabase()' is defined in 'include.inc.php'
  208. if (preg_match("/^(edit|delet)$/", $queryAction))
  209. {
  210. $affectedRows = ($result ? mysqli_affected_rows ($connection) : 0); // get the number of rows that were modified (or return 0 if an error occurred)
  211. if ($affectedRows == 0) // no rows were affected by the update, i.e., the query must have been deleted in the meantime!
  212. // NOTE: Previously, we did return "Warning_SavedQueryDoesNotExistAnymore": "This saved query does not exist anymore".
  213. // However, MySQL does also return 0 if nothing was changed since identical form data were submitted!
  214. // So, if '$affectedRows=0', it would be better to check for the existence of the record and adopt the error message accordingly.
  215. // Currently, we simply return a more generic warning message (the same warning message is returned by 'duplicate_modify.php').
  216. {
  217. // return an appropriate error message:
  218. $HeaderString = returnMsg("Nothing was changed by your query!", "warning", "strong", "HeaderString"); // function 'returnMsg()' is defined in 'include.inc.php'
  219. // update the 'userQueries' session variable:
  220. getUserQueries($loginUserID); // function 'getUserQueries()' is defined in 'include.inc.php'
  221. // Relocate back to the 'Edit Query' form (script 'query_manager.php'):
  222. header("Location: " . $_SERVER['HTTP_REFERER']); // w.r.t. to '$_SERVER['HTTP_REFERER']' vs '$referer' see NOTE above
  223. exit; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !EXIT! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  224. }
  225. }
  226. elseif ($queryAction == "add") // Get the query id that was created:
  227. $queryID = @ mysqli_insert_id($connection); // find out the unique ID number of the newly created query (Note: this function should be called immediately after the
  228. // SQL INSERT statement! After any subsequent query it won't be possible to retrieve the auto_increment identifier value for THIS record!)
  229. // update the 'userQueries' session variable:
  230. getUserQueries($loginUserID); // function 'getUserQueries()' is defined in 'include.inc.php'
  231. // Build correct header message:
  232. if ($queryAction == "add")
  233. $HeaderString = $loc["SavedQueryAdded"]; // before I18n, we did use: "The query no. " . $queryID . " has been successfully " . $queryAction . "ed."
  234. elseif ($queryAction == "edit")
  235. $HeaderString = $loc["SavedQueryEdited"];
  236. elseif ($queryAction == "delet")
  237. $HeaderString = $loc["SavedQueryDeleted"];
  238. $HeaderString = returnMsg($HeaderString, "", "", "HeaderString"); // function 'returnMsg()' is defined in 'include.inc.php'
  239. // (4) Call 'index.php' which will display the header message
  240. // (routing feedback output to a different script page will avoid any reload problems effectively!)
  241. header("Location: index.php");
  242. // --------------------------------------------------------------------
  243. // (5) CLOSE CONNECTION
  244. disconnectFromMySQLDatabase(); // function 'disconnectFromMySQLDatabase()' is defined in 'include.inc.php'
  245. // --------------------------------------------------------------------
  246. ?>