]> CyberLeo.Net >> Repos - Github/YOURLS.git/blob - includes/functions.php
- Renamed insert.php to admin.php
[Github/YOURLS.git] / includes / functions.php
1 <?php\r
2 /*\r
3  * YOURLS\r
4  * Function library\r
5  */\r
6  \r
7 // Bump this when updating the SVN repo\r
8 define('YOURLS_VERSION', '1.3');\r
9 \r
10 // function to convert an integer (1337) to a string (3jk). Input integer processed as a string to beat PHP's int max value\r
11 function yourls_int2string( $id ) {\r
12         $str = yourls_base2base(trim(strval($id)), 10, YOURLS_URL_CONVERT);\r
13         if (YOURLS_URL_CONVERT <= 37)\r
14                 $str = strtolower($str);\r
15         return $str;\r
16 }\r
17 \r
18 // function to convert a string (3jk) to an integer (1337)\r
19 function yourls_string2int( $str ) {\r
20         if (YOURLS_URL_CONVERT <= 37)\r
21                 $str = strtolower($str);\r
22         return yourls_base2base(trim($str), YOURLS_URL_CONVERT, 10);\r
23 }\r
24  \r
25 // Function: Parse HTTP Auth Header\r
26 function yourls_http_digest_parse($txt) {\r
27     $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);\r
28     $data = array();\r
29     preg_match_all('@(\w+)=(?:([\'"])([^$2]+)$2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);   \r
30     foreach ($matches as $m) {\r
31         $data[$m[1]] = $m[3] ? trim($m[3],"\",'") : trim($m[4],"\",'");\r
32         unset($needed_parts[$m[1]]);\r
33     }   \r
34     return $needed_parts ? false : $data;\r
35 }\r
36 \r
37 // Prompt for Authentication\r
38 function yourls_auth_headers($realm = '') {\r
39         header('HTTP/1.1 401 Unauthorized');\r
40         header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');\r
41         die('Sorry! <a href="'.YOURLS_SITE.'/admin.php">Retry</a>.');\r
42 }\r
43 \r
44 // Make sure a link id (site.com/1fv) is valid.\r
45 function yourls_sanitize_string ($in) {\r
46         if (YOURLS_URL_CONVERT <= 37)\r
47                 $in = strtolower($in);\r
48         return substr(preg_replace('/[^a-zAZ0-9]/', '', $in), 0, 12);\r
49 }\r
50 \r
51 // make sure there's one and only one 'http://' at the beginning (prevents omitting or pasting a URL right after the default 'http://')\r
52 function yourls_sanitize_url($url) {\r
53         return preg_replace('#^(http://)+#', 'http://', 'http://'.$url);\r
54 }\r
55 \r
56 // Make sure an id link is a valid integer (PHP's intval() limits to too small numbers)\r
57 function yourls_sanitize_int($in) {\r
58         return ( substr(preg_replace('/[^0-9]/', '', strval($in) ), 0, 20) );\r
59 }\r
60 \r
61 // Make sure a integer is safe\r
62 // Note: this is not checking for integers, since integers on 32bits system are way too limited\r
63 // TODO: find a way to validate as integer\r
64 function yourls_intval($in) {\r
65         return mysql_real_escape_string($in);\r
66 }\r
67 \r
68 \r
69 // Check to see if a given integer id is reserved (ie reserved URL or an existing page)\r
70 // Returns bool\r
71 function yourls_is_reserved_id($id) {\r
72         global $yourls_reserved_URL;\r
73         $keyword = yourls_int2string( yourls_intval($id) );\r
74         if ( in_array( $keyword, $yourls_reserved_URL)\r
75                 or file_exists(dirname(dirname(__FILE__))."/pages/$keyword.php")\r
76                 or is_dir(dirname(dirname(__FILE__))."$keyword")\r
77         )\r
78                 return true;\r
79         \r
80         return false;\r
81 }\r
82 \r
83 // Function: Get IP Address\r
84 function yourls_get_IP() {\r
85         if(!empty($_SERVER['HTTP_CLIENT_IP'])) {\r
86                 $ip_address = $_SERVER['HTTP_CLIENT_IP'];\r
87         } else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {\r
88                 $ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];\r
89         } else if(!empty($_SERVER['REMOTE_ADDR'])) {\r
90                 $ip_address = $_SERVER['REMOTE_ADDR'];\r
91         } else {\r
92                 $ip_address = '';\r
93         }\r
94         if(strpos($ip_address, ',') !== false) {\r
95                 $ip_address = explode(',', $ip_address);\r
96                 $ip_address = $ip_address[0];\r
97         }\r
98         return $ip_address;\r
99 }\r
100 \r
101 // Add the "Edit" row\r
102 function yourls_table_edit_row($id, $db) {\r
103         $id = yourls_intval($id);\r
104         $table = YOURLS_DB_TABLE_URL;\r
105         $url = $db->get_row("SELECT `url` FROM `$table` WHERE `id` = '$id';");\r
106         $safe_url = stripslashes($url->url);\r
107         $keyword = yourls_int2string($id);\r
108         if($url) {\r
109                 $return = <<<RETURN\r
110                 <tr id="edit-$id" class="edit-row">\r
111                 <td colspan="6">Edit: <strong>original URL</strong>:<input type="text" id="edit-url-$id" name="edit-url-$id" value="$safe_url" class="text" size="100" />\r
112                         <strong>short URL</strong>:<input type="text" id="edit-id-$id" name="edit-id-$id" value="$keyword" class="text" size="10" />\r
113                 </td>\r
114                 <td colspan="1"><input type="button" id="edit-submit-$id" name="edit-submit-$id" value="Save" title="Save new values" class="button" onclick="edit_save('$id');" />&nbsp;<input type="button" id="edit-close-$id" name="edit-close-$id" value="X" title="Cancel editing" class="button" onclick="hide_edit('$id');" /></td>\r
115                 </tr>\r
116 RETURN;\r
117         } else {\r
118                 $return = '<tr><td colspan="7">Invalid URL ID</td></tr>';\r
119         }\r
120         \r
121         return $return;\r
122 }\r
123 \r
124 // Add a link row\r
125 function yourls_table_add_row( $id, $keyword, $url, $ip, $clicks, $timestamp ) {\r
126         $date = date( 'Y M d H:i', $timestamp+( yourls_HOURS_OFFSET * 3600) );\r
127         $clicks = number_format($clicks);\r
128         $www = YOURLS_SITE;\r
129         \r
130         return <<<ROW\r
131         <tr id="id-$id">\r
132                 <td id="keyword-$id">$keyword</td>\r
133                 <td id="url-$id"><a href="$url" title="$url">$url</a></td>\r
134                 <td id="shorturl-$id"><a href="$www/$keyword" title="$www/$keyword">$www/$keyword</a></td>\r
135                 <td id="timestamp-$id">$date</td>\r
136                 <td>$ip</td>\r
137                 <td>$clicks</td>\r
138                 <td class="actions">\r
139                 <input type="button" id="edit-button-$id" name="edit-button" value="Edit" class="button" onclick="edit('$id');" />&nbsp;<input type="button" id="delete-button-$id" name="delete-button" value="Del" class="button" onclick="remove('$id');" />\r
140                 </td>\r
141         </tr>\r
142 ROW;\r
143 }\r
144 \r
145 // Get next id a new link will have if no custom keyword provided\r
146 function yourls_get_next_decimal($db) {\r
147         $table = YOURLS_DB_TABLE_NEXTDEC;\r
148         return $db->get_var("SELECT `next_id` FROM `$table`");\r
149 }\r
150 \r
151 // Update id for next link with no custom keyword\r
152 function yourls_update_next_decimal($int = '', $db) {\r
153         $int = ( $int == '' ) ? 'next+1' : (int)$int ;\r
154         $table = YOURLS_DB_TABLE_NEXTDEC;\r
155         return $db->query("UPDATE `$table` set next_id=$int");\r
156 }\r
157 \r
158 // Delete a link in the DB\r
159 function yourls_delete_link_by_id($id, $db) {\r
160         $table = YOURLS_DB_TABLE_URL;\r
161         $id = yourls_intval($id);\r
162         return $db->query("DELETE FROM `$table` WHERE `id` = $id;");\r
163 }\r
164 \r
165 // SQL query to insert a new link in the DB. Needs sanitized data. Returns boolean for success or failure of the inserting\r
166 function yourls_insert_link_in_db($url, $id, $db) {\r
167         $table = YOURLS_DB_TABLE_URL;\r
168         $timestamp = date('Y-m-d H:i:s');\r
169         $ip = yourls_get_IP();\r
170         return $db->query("INSERT INTO `$table` VALUES($id, '$url', '$timestamp', '$ip', 0);");\r
171 }\r
172 \r
173 // Add a new link in the DB, either with custom keyword, or find one\r
174 function yourls_add_new_link($url, $keyword = '', $db) {\r
175         if ( !$url or $url == 'http://' ) {\r
176                 $return['status'] = 'fail';\r
177                 $return['message'] = 'Missing URL input';\r
178                 return $return;\r
179         }\r
180 \r
181         $table = YOURLS_DB_TABLE_URL;\r
182         $url = mysql_real_escape_string(yourls_sanitize_url($url));\r
183         $strip_url = stripslashes($url);\r
184         $url_exists = $db->get_row("SELECT id,url FROM `$table` WHERE `url` = '".$strip_url."';");\r
185         $ip = yourls_get_IP();\r
186         $return = array();\r
187 \r
188         // New URL : store it\r
189         if( !$url_exists ) {\r
190 \r
191                 // Custom keyword provided\r
192                 if ($keyword) {\r
193                         $keyword = yourls_sanitize_string($keyword);\r
194                         if (!yourls_keyword_is_free($keyword, $db)) {\r
195                                 // This id either reserved or taken already\r
196                                 $return['status'] = 'fail';\r
197                                 $return['message'] = 'URL id '.$keyword.' already exists in database or is reserved';\r
198                         } else {\r
199                                 // all clear, store !\r
200                                 $id = yourls_string2int($keyword);\r
201                                 yourls_insert_link_in_db($url, $id, $db);\r
202                                 $return['url'] = array('id' => $id, 'keyword' => $keyword, 'url' => $strip_url, 'date' => date('Y-m-d H:i:s'), 'ip' => yourls_get_IP() );\r
203                                 $return['status'] = 'success';\r
204                                 $return['message'] = $strip_url.' (ID: '.$keyword.') added to database';\r
205                                 $return['html'] = yourls_table_add_row( $id, $keyword, $url, yourls_get_IP(), 0, time() );\r
206                                 $return['shorturl'] = YOURLS_SITE .'/'. $keyword;\r
207                         }\r
208 \r
209                 // Create random keyword        \r
210                 } else {\r
211                         $timestamp = date('Y-m-d H:i:s');\r
212                         $id = yourls_get_next_decimal($db);\r
213                         do {\r
214                                 $add_url = yourls_insert_link_in_db($url, $id, $db);\r
215                                 $free = !yourls_is_reserved_id( $id );\r
216                                 $ok = ($free && $add_url);\r
217                                 if ( $ok === false && $add_url === 1 ) {\r
218                                         // we stored something, but shouldn't have (ie reserved id)\r
219                                         $delete = yourls_delete_link_by_id( $id, $db );\r
220                                         $return['extra_info'] .= '(deleted '.$id.')';\r
221                                 } else {\r
222                                         // everything ok, populate needed vars\r
223                                         $keyword = yourls_int2string($id);\r
224                                         $return['url'] = array('id' => $id, 'keyword' => $keyword, 'url' => $strip_url, 'date' => $timestamp, 'ip' => $ip);\r
225                                         $return['status'] = 'success';\r
226                                         $return['message'] = $strip_url.' (ID: '.$id.') added to database';\r
227                                         $return['html'] = yourls_table_add_row( $id, $keyword, $url, $ip, 0, time() );\r
228                                         $return['shorturl'] = YOURLS_SITE .'/'. $keyword;\r
229                                 }\r
230                                 $id++;\r
231                         } while (!$ok);\r
232                         yourls_update_next_decimal($id, $db);\r
233                 }\r
234         } else {\r
235                 // URL was already stored\r
236                 $return['status'] = 'fail';\r
237                 $return['message'] = $strip_url.' already exists in database';\r
238                 $return['shorturl'] = YOURLS_SITE .'/'. yourls_int2string( $url_exists->id );\r
239         }\r
240 \r
241         return $return;\r
242 }\r
243 \r
244 \r
245 // Edit a link\r
246 function yourls_edit_link($url, $id, $keyword='', $db) {\r
247         $table = YOURLS_DB_TABLE_URL;\r
248         $url = mysql_real_escape_string(yourls_sanitize_url($url));\r
249         $id = yourls_intval($id);\r
250         $strip_url = stripslashes($url);\r
251         $old_url = $db->get_var("SELECT `url` FROM `$table` WHERE `id` = '".$id."';");\r
252         \r
253         \r
254         // Check if new URL is not here already\r
255         if ($old_url != $url) {\r
256                 $url_exists = intval($db->get_var("SELECT id FROM `$table` WHERE `url` = '".$strip_url."';"));\r
257         } else {\r
258                 $url_exists = false;\r
259         }\r
260         \r
261         // Check if the new keyword is not here already\r
262         $newid = ( $keyword ? yourls_string2int($keyword) : $id );\r
263         if ($newid != $id) {\r
264                 $id_exists = intval($db->get_var("SELECT id FROM `$table` WHERE `id` = '".$newid."';"));\r
265                 $id_free = yourls_keyword_is_free($keyword, $db);\r
266                 $id_is_ok = ($id_exists == 0) && $id_free;\r
267         } else {\r
268                 $id_is_ok = true;\r
269         }\r
270         \r
271         // All clear, update\r
272         if($url_exists == 0 && $id_is_ok ) {\r
273                 $timestamp4screen = date( 'Y M d H:i', time()+( yourls_HOURS_OFFSET * 3600) );\r
274                 $timestamp4db = date('Y-m-d H:i:s', time()+( yourls_HOURS_OFFSET * 3600) );\r
275                 $update_url = $db->query("UPDATE `$table` SET `url` = '$url', `timestamp` = '$timestamp4db', `id` = '$newid' WHERE `id` = $id;");\r
276                 if($update_url) {\r
277                         $return['url'] = array('id' => $newid, 'keyword' => $keyword, 'shorturl' => YOURLS_SITE.'/'.$keyword, 'url' => $strip_url, 'date' => $timestamp4screen);\r
278                         $return['status'] = 'success';\r
279                         $return['message'] = 'Link updated in database';\r
280                 } else {\r
281                         $return['status'] = 'fail';\r
282                         $return['message'] = 'Error updating '.$strip_url.' (ID: '.$id.') to database';\r
283                 }\r
284         \r
285         // Nope\r
286         } else {\r
287                 $return['status'] = 'fail';\r
288                 $return['message'] = 'URL or keyword already exists in database';\r
289         }\r
290         \r
291         return $return;\r
292 }\r
293 \r
294 \r
295 // Check if keyword id is free (ie not already taken, and not reserved)\r
296 function yourls_keyword_is_free($str, $db) {\r
297         $table = YOURLS_DB_TABLE_URL;\r
298         $id = yourls_string2int($str);\r
299         if ( yourls_is_reserved_id($id) )\r
300                 return false;\r
301                 \r
302         $already_exists = intval($db->get_var("SELECT `id` FROM `$table` WHERE `id` = '".$id."';"));\r
303         if ( $already_exists )\r
304                 return false;\r
305 \r
306         return true;\r
307 }\r
308 \r
309 \r
310 // Display a page\r
311 function yourls_page($page) {\r
312         $include = dirname(dirname(__FILE__))."/pages/$page.php";\r
313         if (!file_exists($include)) {\r
314                 die("Page '$page' not found");\r
315         }\r
316         include($include);\r
317         die();  \r
318 }\r
319 \r
320 // Connect to DB\r
321 function yourls_db_connect() {\r
322         if (!defined('YOURLS_DB_USER')\r
323                 or !defined('YOURLS_DB_PASS')\r
324                 or !defined('YOURLS_DB_NAME')\r
325                 or !defined('YOURLS_DB_HOST')\r
326                 or !class_exists('ezSQL_mysql')\r
327         ) die ('DB config/class missing');\r
328         \r
329         return new ezSQL_mysql(YOURLS_DB_USER, YOURLS_DB_PASS, YOURLS_DB_NAME, YOURLS_DB_HOST);\r
330 }\r
331 \r
332 // Return JSON output. Compatible with PHP prior to 5.2\r
333 function yourls_json_encode($array) {\r
334         if (function_exists('json_encode')) {\r
335                 return '('.json_encode($array).')';\r
336         } else {\r
337                 require_once(dirname(__FILE__).'/functions-json.php');\r
338                 return '('.yourls_array_to_json($array).')';\r
339         }\r
340 }\r
341 \r
342 // Return XML output.\r
343 function yourls_xml_encode($array) {\r
344         require_once(dirname(__FILE__).'/functions-xml.php');\r
345         return yourls_array_to_xml($array);\r
346 }\r