PageRenderTime 36ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/frontend/php/include/form.php

#
PHP | 193 lines | 94 code | 32 blank | 67 comment | 20 complexity | f988500ecf822ae7acec8537d7c9971b MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php
  2. # <one line to give a brief idea of what this does.>
  3. #
  4. # Copyright 2004-2006 (c) Mathieu Roy <yeupou--gnu.org>
  5. #
  6. # This file is part of Savane.
  7. #
  8. # Savane is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # Savane is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. require_once(dirname(__FILE__).'/dnsbl.php');
  21. require_once(dirname(__FILE__).'/spam.php');
  22. # To use this form that disallow duplicates:
  23. # - form_header must be used on the form
  24. # - form_check must be used before any insert in the db after submission
  25. # - form_clean must be used after succesful item submission
  26. #
  27. # Start the form with unique ID, store it in the database
  28. function form_header ($action, $form_id=false, $method="post", $extra=false)
  29. {
  30. if ($extra)
  31. { $extra = " $extra"; };
  32. # Keep previous form id, in case of form that are recreated on failure
  33. if (!$form_id)
  34. {
  35. mt_srand((double)microtime()*1000000);
  36. $form_id=md5(mt_rand(0,1000000));
  37. }
  38. $result = db_autoexecute('form',
  39. array('form_id' => $form_id,
  40. 'timestamp' => time(),
  41. 'user_id' => user_getid()),
  42. DB_AUTOQUERY_INSERT);
  43. if (db_affected_rows($result) != 1)
  44. { fb(_("System error while creating the form, report it to admins"), 1); }
  45. return '
  46. <form action="'.$action.'" method="'.$method.'"'.$extra.'>'.form_input("hidden","form_id",$form_id);
  47. }
  48. # Usual input
  49. function form_input ($type, $name, $value="", $extra=false)
  50. {
  51. if ($value != "")
  52. { $value = 'value="'.$value.'"'; }
  53. if ($extra)
  54. { $extra = " $extra"; };
  55. return '
  56. <input type="'.$type.'" id="'.$name.'" name="'.$name.'" '.$value.$extra.' />';
  57. }
  58. # Special input: textarea
  59. function form_textarea ($name, $value="", $extra=false)
  60. {
  61. if ($extra)
  62. { $extra = " $extra"; };
  63. return '
  64. <textarea name="'.$name.'"'.$extra.'>'.$value.'</textarea>';
  65. }
  66. # Add submit button
  67. function form_submit($text=false, $submit_name="update", $extra=false)
  68. {
  69. if (!$text)
  70. { $text = _("Submit"); }
  71. # Add a trap for spammers: a text input that will have to be kept empty.
  72. # This wont prevent tailored bots to spam, but that should prevent
  73. # the rest of them, which is good enough (task #4151).
  74. # Sure, some bots will someday implement CSS support, but the ones that does
  75. # not will not disappear as soon as this happen.
  76. $trap = '';
  77. if (empty($GLOBALS['int_trapisset']) && !user_isloggedin())
  78. {
  79. $trap = " ".form_input("text", "website", "http://");
  80. $GLOBALS['int_trapisset'] = true;
  81. }
  82. return form_input("submit", $submit_name, $text, $extra).$trap;
  83. }
  84. # Close the form, with submit button
  85. function form_footer ($text=false, $submit_name="update")
  86. {
  87. return '
  88. <div class="center">
  89. '.form_submit($text, $submit_name).'
  90. </div>
  91. </form>';
  92. }
  93. # Check whether this is a duplicate or not: return true if the form
  94. # is ok.
  95. # Exit if we found sql wildcards: forged form, probably.
  96. # We do need this extra check for anynomous users. Logged in users can forge
  97. # their id and remove all the form id of their user, if they wish. Its their
  98. # problem.
  99. #
  100. # form_check is also used as a cross-side request forgery (CSRF) protection.
  101. function form_check ($form_id)
  102. {
  103. if (!empty($GLOBALS['sys_debug_noformcheck']))
  104. return 1;
  105. # First, check for spambots
  106. # (will kill the session if necessary)
  107. form_check_nobot();
  108. if (user_getid() == 0 &&
  109. (!preg_match('/^[a-z0-9]*$/', $form_id)))
  110. {
  111. fb(_("Unrecognized unique form_id"), 1);
  112. return 0;
  113. }
  114. # See bug #6983
  115. # We must clean the form id right now. This is not how the form id mechanism
  116. # was designed.
  117. #
  118. # Originally, form id was supposed to be deleted only when we are sure
  119. # that the form was posted.
  120. # However, since apache & all are multithreaded, you can end up with the
  121. # case that the delay between the initial check and the end of the form
  122. # is long enough to make possible a duplicate.
  123. #
  124. # Now, the check will remove the id. If the remove fail, it means that
  125. # the form id no longer exists and then we exit. We will have only one
  126. # SQL request, reducing as much as possible delays.
  127. $success = db_affected_rows(db_execute("DELETE FROM form WHERE user_id=? AND form_id=?",
  128. array(user_getid(), $form_id)));
  129. if (!$success)
  130. {
  131. fb(_("Duplicate Post: this form was already submitted."),1);
  132. return 0;
  133. }
  134. # Always do a dnsbl check when such form is sent
  135. # (it will kill the submission if necessary)
  136. dnsbl_check();
  137. # Also does a check against savane own blacklist
  138. # (will never forbid post to logged-in users)
  139. spam_bancheck();
  140. return 1;
  141. }
  142. # Remove form_id from database: the item was posted
  143. function form_clean ($form_id)
  144. {
  145. # Form_id are now directly removed by form_check
  146. return 1;
  147. }
  148. # Check whether the trap field has been filled. If so, refuse the post.
  149. # This test should probably be made before remove form id, to be
  150. # dumbuser-compliant
  151. function form_check_nobot ()
  152. {
  153. extract(sane_import('request', array('website')));
  154. if ($website != "" && $website != "http://")
  155. {
  156. # Not much explanation on the reject, since we are hunting spammers
  157. exit_log("filled the spam trap special field");
  158. exit_missing_param();
  159. }
  160. return 1;
  161. }