PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/global_functions.php

https://bitbucket.org/paullik/dotophp
PHP | 448 lines | 172 code | 59 blank | 217 comment | 40 complexity | 92245303448ea937b06f70baba9818ea MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * @file src/global_functions.php
  4. * @brief Globally used functions
  5. * @author Paul Barbu
  6. *
  7. * @ingroup globalFiles
  8. */
  9. /**
  10. * @defgroup globalFiles Global files
  11. */
  12. /**
  13. * Filters the user's input(sanitizes it) to avoid building an attack vector
  14. *
  15. * This function accepts a variable number of arguments
  16. *
  17. * @return array $filteredInput the sanitized input on the same position in the
  18. * array as it's place in the args list
  19. */
  20. function filterInput(){/*{{{*/
  21. $filteredInput = array();
  22. $args = func_get_args();
  23. foreach($args as $text){
  24. $filteredInput[] = strip_tags($text);
  25. }
  26. return $filteredInput;
  27. }/*}}}*/
  28. /**
  29. * Generate the activation code
  30. *
  31. * Needed by the user on registration or account recovery
  32. *
  33. * @param string $nick user's nickname
  34. *
  35. * @return string activation code
  36. */
  37. function genActivationCode($nick){/*{{{*/
  38. return implode('', array_slice(str_split(sha1($nick . time())), 0, 10));
  39. }/*}}}*/
  40. /**
  41. * Tells whether the given array contain the specified keys
  42. *
  43. * You can pass a variable number of strings as arguments
  44. *
  45. * @param array $arr the array to be checked(can be a superglobal too)
  46. *
  47. * @return an array consisting of a BOOL value and a NULL or the error string,
  48. * array(BOOL, string)
  49. */
  50. function containsKeys($arr){/*{{{*/
  51. $keys = array_slice(func_get_args(), 1);
  52. foreach($keys as $key){
  53. if(!array_key_exists($key, $arr)){
  54. return array(FALSE, $key . " does not exists in " . $arr);
  55. }
  56. }
  57. return array(TRUE, NULL);
  58. }/*}}}*/
  59. /**
  60. * Checks if the name is valid according to the name field
  61. *
  62. * @param string $name the name to be verified
  63. *
  64. * @return BOOL TRUE if the name is valid, else FALSE
  65. */
  66. function isValidName($name){/*{{{*/
  67. return (strlen($name) <= 20 && preg_match("/^[\p{Ll}\p{Lu}][\p{Ll}\p{Lu}\p{Nd}_-]*$/u", $name));
  68. }/*}}}*/
  69. /**
  70. * Checks if a given nickname is valid(according to the domain fileds)
  71. *
  72. * @param string $nick the nickname to be checked
  73. *
  74. * @return BOOL TRUE if the nickname is valid, else FALSE
  75. */
  76. function isValidNick($nick){/*{{{*/
  77. return (strlen($nick) <= 20 && preg_match("/^[a-z][a-z0-9_-]*$/", $nick));
  78. }/*}}}*/
  79. /**
  80. * Checks whether the given email is valid or not
  81. *
  82. * @param string $email string to be checked
  83. *
  84. * @return BOOL TRUE if the email is valid, else FALSE
  85. */
  86. function isValidMail($email){/*{{{*/
  87. //thanks to: http://www.regular-expressions.info/email.html
  88. return (bool)preg_match("/[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/", $email);
  89. }/*}}}*/
  90. /**
  91. * Checks the validity of a string representing a city
  92. *
  93. * @param string $city the string to be checked
  94. *
  95. * @return BOOL TRUE if the city is valid, else FALSE
  96. */
  97. function isValidCity($city){/*{{{*/
  98. return (strlen($city) <= 30 && preg_match("/^[\p{Lu}\p{Ll}\s]+$/u", $city));
  99. }/*}}}*/
  100. /**
  101. * Checks if a phone number entered as a string is valid
  102. *
  103. * @param string $phone the string to be checked
  104. *
  105. * @return BOOL TRUE if the phone number is valid, else, FALSE
  106. */
  107. function isValidPhone($phone){/*{{{*/
  108. return (strlen($phone) <= 20 && preg_match("/^[0-9()-\s\/]+$/", $phone));
  109. }/*}}}*/
  110. /**
  111. * Checks if a birthdate was entered in the required format
  112. *
  113. * @param string $bdate the string to be checked
  114. *
  115. * @return BOOL TRUE if the format is valid, else, FALSE
  116. */
  117. function isValidBDate($bdate){/*{{{*/
  118. return (10 == strlen($bdate) && preg_match('/\d{2}-\d{2}-\d{4}/', $bdate));
  119. }/*}}}*/
  120. /**
  121. * Checks if a description is valid
  122. *
  123. * @param string $desc the string to be checked
  124. *
  125. * @return BOOL TRUE if the description is valid, else, FALSE
  126. */
  127. function isValidDesc($desc){/*{{{*/
  128. return (strlen($desc) <= 100 && preg_match("/^[\p{Ll}\p{Lu}\p{Nd}\p{Po}\p{Ps}\p{Pe}\p{Sm}\p{Pd}\s\$\^]+$/u", $desc));
  129. }/*}}}*/
  130. /**
  131. * Check if the captcha code entered matches the generated one
  132. *
  133. * @param string $captcha the genereated captcha code
  134. * @param string $captcha_input the code user entered
  135. *
  136. * @return BOOL TRUE if the two string match, else, FALSE
  137. */
  138. function isValidCaptcha($captcha, $captcha_input){/*{{{*/
  139. return strtolower($captcha_input) == $captcha;
  140. }/*}}}*/
  141. /**
  142. * Check the security data (question and answer)
  143. *
  144. * @param string $data the question or the answer to be checked
  145. *
  146. * @return BOOL TRUE if the data is valid, else FALSE
  147. */
  148. function isValidSecurityData($data){/*{{{*/
  149. $len = strlen($data);
  150. return ($len >= 8 && $len <= 255 && preg_match('/^[\s\p{Ll}\p{Lu}\p{Po}\p{Nd}]+$/u', $data));
  151. }/*}}}*/
  152. /**
  153. * Query the DB to check if the email and/or nickname are supplied correctly
  154. *
  155. * @param mysqli $link a link identifier returned by mysqli_connect() or mysqli_init()
  156. * @param string $nickname user's nickname
  157. * @param string $email user's email
  158. *
  159. * @return MATCHING_NICK if the user's nick is found in the DB, MATCHING_MAIL if the email
  160. * is found, else(the nick and the email are not found) NO_MATCH
  161. */
  162. function isUser($link, $nickname = NULL, $email = NULL){/*{{{*/
  163. $query = 'SELECT nick, email FROM user WHERE ';
  164. $query_conditions = array();
  165. if(isValidNick($nickname)){
  166. $query_conditions[] = "nick = '" . $nickname . "'";
  167. }
  168. if(isValidMail($email)){
  169. $query_conditions[] = "email = '" . $email . "'";
  170. }
  171. if(empty($query_conditions)){
  172. return FALSE;
  173. }
  174. $result = mysqli_query($link, $query . implode(" OR ", $query_conditions));
  175. $user = mysqli_fetch_all($result, MYSQLI_ASSOC);
  176. if(empty($user)){
  177. return NO_MATCH;
  178. }
  179. foreach($user as $candidate){
  180. if($candidate['nick'] == $nickname){
  181. return MATCHING_NICK;
  182. }
  183. elseif($candidate['email'] == $email){
  184. return MATCHING_MAIL;
  185. }
  186. }
  187. }/*}}}*/
  188. /**
  189. * Add the newly created user to the pending table
  190. *
  191. * This function and the one that adds the user must be used in a MySQL
  192. * transaction to avoid user ID's mismatching.
  193. *
  194. * @param mysqli $link a link identifier returned by mysqli_connect() or mysqli_init()
  195. * @param string $code generated activation code
  196. *
  197. * @return BOOL TRUE on success, else FALSE
  198. */
  199. function addPendingUser($link, $code){/*{{{*/
  200. $query = "INSERT INTO pending (user_id, code) VALUES(LAST_INSERT_ID(), '";
  201. $result = mysqli_query($link, $query . $code . "');");
  202. if(!$result){
  203. return FALSE;
  204. }
  205. return TRUE;
  206. }/*}}}*/
  207. /**
  208. * Choose a string depending on the state of an user
  209. *
  210. * 'OUT' means not-logged in user \n
  211. * 'IN' means logged in user \n
  212. * This function should be useed in the configuration file \n
  213. *
  214. * @param string $in_str this string will be returned if the user's state is IN
  215. * @param string $out_str this string will be returned if the user's state is OUT
  216. *
  217. * @return string $in_str or $out_str
  218. */
  219. function getStrByState($in_str, $out_str){/*{{{*/
  220. if(isset($_SESSION['uid'])){
  221. return $in_str;
  222. }
  223. return $out_str;
  224. }/*}}}*/
  225. /**
  226. * Function to name the printf specifiers
  227. *
  228. * Credits: http://stackoverflow.com/questions/7435233/name-php-specifiers-in-printf-strings/7435397#7435397
  229. * Usage:
  230. @code
  231. $foo = array('age' => 5, 'name' => 'john');
  232. echo vsprintf_named("%(name)s is %(age)02d", $foo);
  233. @endcode
  234. *
  235. * @param string $format the format of the resulting string
  236. * @param array $args the array containing the specifiers as keys and the values
  237. * the specifiers will be replaced with
  238. *
  239. * @return the string to be sent as output(e.g. echo)
  240. */
  241. function vsprintf_named($format, $args) {/*{{{*/
  242. $names = preg_match_all('/%\((.*?)\)/', $format, $matches, PREG_SET_ORDER);
  243. $values = array();
  244. foreach($matches as $match) {
  245. $values[] = $args[$match[1]];
  246. }
  247. $format = preg_replace('/%\((.*?)\)/', '%', $format);
  248. return vsprintf($format, $values);
  249. }/*}}}*/
  250. /**
  251. * Display array contents as HTML @code<option></option>@endcode
  252. *
  253. * Helper function
  254. *
  255. * @param array $text the text to be written
  256. * @param mixed $values the values to assign the options
  257. * @param string $selectedValue (default: NULL) which element(matching the value) to be selected in the
  258. * options list, if NULL none will be selected
  259. * @param string $template template for the HTML @code<option>@endcode tag
  260. * @param string $selected_template template for the HTML selected @code<option>@endcode tag
  261. *
  262. * @return BOOL TRUE on success, else, FALSE
  263. */
  264. function arrayToOption($text, $values, $selectedValue = NULL, $template='<option value="%(value)s">%(text)s</option>',/*{{{*/
  265. $selected_template='<option value="%(value)s" selected="selected" >%(text)s</option>'){
  266. if(is_array($values) && is_array($text)){
  267. $text_count = count($text);
  268. if($text_count == count($values)){
  269. for($i=0; $i<$text_count; $i++){
  270. if($selectedValue == $values[$i]){
  271. echo vsprintf_named($selected_template, array('text' => $text[$i],
  272. 'value' => $values[$i])) , PHP_EOL;
  273. }
  274. else{
  275. echo vsprintf_named($template, array('text' => $text[$i],
  276. 'value' => $values[$i])) , PHP_EOL;
  277. }
  278. }
  279. }
  280. else{
  281. return FALSE;
  282. }
  283. }
  284. else{
  285. return FALSE;
  286. }
  287. return TRUE;
  288. }/*}}}*/
  289. /**
  290. * Create(or open) a log file and write(or append) a message
  291. *
  292. * A log file must have the 'log' extension
  293. * In front of every message the date will be appended.
  294. *
  295. * @param string $path path to the file to be written (relative to MODULES_ROOT)
  296. * @param mixed $data the exact message to be written (no new lines are added
  297. * automatically)
  298. *
  299. * @return TRUE if the operation has succedded, else FALSE
  300. */
  301. function writeLog($path, $data){/*{{{*/
  302. $path .= strpos($path, '.log') !== strlen($path)-4 ? '.log' : NULL;
  303. return error_log(date(DATE_FORMAT) . ' - ' . $data, 3, $path);
  304. }/*}}}*/
  305. /**
  306. * Creates a query and inserts data into a database
  307. *
  308. * @param mysqli $link a link identifier returned by mysqli_connect() or mysqli_init()
  309. * @param string $table the name of the table where the insert must be made
  310. * @param array $data associative array, the keys will be used for the column
  311. * names and the values will be used in VALUES()
  312. *
  313. * @return TRUE is the insert was made successfully, else FALSE
  314. */
  315. function insertIntoDB($link, $table, $data){/*{{{*/
  316. $result = mysqli_query($link, 'INSERT INTO ' . $table . '(' . implode(',',
  317. array_keys($data)) . ') VALUES(\'' . implode("', '", $data) . '\');');
  318. if(!$result){
  319. return FALSE;
  320. }
  321. return TRUE;
  322. }/*}}}*/
  323. /**
  324. * Insert or update a session's expiry timestamp
  325. *
  326. * @param mysqli $link a link identifier returned by mysqli_connect() or mysqli_init()
  327. * @param string $sessid the session's id to be inserted or updated
  328. * @param int $offset number of seconds starting from now until the session
  329. * expires
  330. * @param int $userid user's ID that started the session
  331. *
  332. * @return TRUE if the insert succeeded else FALSE
  333. */
  334. function session_set_expiry_offset($link, $sessid, $offset, $userid){/*{{{*/
  335. $result = mysqli_query($link, "REPLACE INTO session(id,user_id, expiry_ts) VALUES('"
  336. . $sessid . "'," . $userid . ", DATE_ADD(CURRENT_TIMESTAMP, INTERVAL "
  337. . $offset . ' SECOND))');
  338. return $result;
  339. }/*}}}*/
  340. /**
  341. * Clean up the expired sessions in the DB
  342. *
  343. * @param mysqli $link a link identifier returned by mysqli_connect() or mysqli_init()
  344. *
  345. * @return number of cleaned sessions or FALSE on error
  346. */
  347. function clean_expired_sess($link){/*{{{*/
  348. return mysqli_query($link, "DELETE FROM session WHERE expiry_ts < CURRENT_TIMESTAMP;");
  349. }/*}}}*/
  350. /**
  351. * Searches recursively a directory the files which match a name
  352. *
  353. * @param string $path path to a directory
  354. * @param string $name file's name to be matched, using glob matching
  355. * @param bool $recursive searches recursively when TRUE
  356. * @param int $flags flags used by php glob(), see: http://php.net/glob
  357. * default: GLOB_MARK
  358. *
  359. * @return array $files containing the path to the matching files
  360. */
  361. function find_files_by_name($path, $name, $recursive = TRUE, $flags = GLOB_MARK){/*{{{*/
  362. $files = array();
  363. if(DIRECTORY_SEPARATOR != substr($path, -1)){
  364. $path .= DIRECTORY_SEPARATOR;
  365. }
  366. if(is_dir($path)){
  367. $d = opendir($path);
  368. $f = glob($path . $name, $flags);
  369. if($f !== FALSE){
  370. foreach($f as $file){
  371. if(DIRECTORY_SEPARATOR != $file[strlen($file)-1]){
  372. $files[] = $file;
  373. }
  374. }
  375. }
  376. while($entry = readdir($d)){
  377. if('.' != $entry && '..' != $entry){
  378. if(is_dir($path . $entry) && $recursive){
  379. $files = array_unique(array_merge(find_files_by_name(
  380. $path . $entry, $name, $recursive, $flags), $files));
  381. }
  382. }
  383. }
  384. closedir($d);
  385. }
  386. return $files;
  387. }/*}}}*/
  388. /* vim: set ts=4 sw=4 tw=80 sts=4 fdm=marker nowrap et :*/