]> dev.renevier.net Git - syp.git/blob - api.php
fixes CHANGES.txt
[syp.git] / api.php
1 <?php
2 /* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD
3    license. */
4
5 function exit_document ($body) {
6     $charset_meta = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
7     exit ("<html>$charset_meta<head></head><body>$body</body></html>");
8 }
9
10 function success ($reason) {
11     exit_document ("<success request=\"$reason\"></success>");
12 }
13
14 function success_changepass ($username) {
15     $res = "<success request=\"changepass\"><user>" .
16             htmlspecialchars ($username) .
17             "</user></success>";
18     exit_document ($res);
19 }
20
21 function success_newuser ($username) {
22     $res = "<success request=\"newuser\"><user>" .
23             htmlspecialchars ($username) .
24             "</user></success>";
25     exit_document ($res);
26 }
27
28 function success_auth ($user) {
29     $res = "<success request=\"$reason\"><user>" . 
30             htmlspecialchars ($user) .
31             "</user></success>";
32     exit_document ($res);
33 }
34
35 function success_feature ($feature, $request) {
36     $res = "<success request=\"$request\"><feature>";
37     $res .= "<id>" .  $feature->id .  "</id>";
38
39     $res .= "<imgurl>" .
40              ($feature->imgpath ? 
41                     image_url_from_imgpath ($feature->imgpath)
42                     : "") .
43              "</imgurl>";
44
45     $res .= "<description>" .
46                  htmlspecialchars ($feature->description) .
47                  "</description>";
48
49     // XXX: we do not use <title> because that would be interpreted and
50     // altered by browers html parser
51     $res .= "<heading>" . 
52             htmlspecialchars ($feature->title) .
53             "</heading>";
54
55     $res .= "<lon>" . $feature->lon . "</lon>";
56     $res .= "<lat>" . $feature->lat . "</lat>";
57     $res .= "</feature></success>";
58     exit_document ($res);
59 }
60
61 function success_delete_feature ($feature) {
62     $res = "<success request=\"del\"><feature>";
63     $res .= "<id>" .  $feature->id .  "</id>";
64     $res .= "</feature></success>";
65     exit_document ($res);
66 }
67
68 function error ($reason) {
69     exit_document ("<error reason=\"$reason\"></error>");
70 }
71
72 function error_newuser_exists () {
73     error ("newuser_exists");
74 }
75
76 function error_feature ($id, $reason) {
77     $res = "<error reason=\"$reason\"><feature>";
78     $res .= "<id>" .  $id .  "</id>";
79     $res .= "</feature></error>";
80     exit_document ($res);
81 }
82
83 function error_nochange ($id) {
84     error_feature ($id, "nochange");
85 }
86 function error_unreferenced ($id) {
87     error_feature ($id, "unreferenced");
88 }
89
90 function error_server () {
91     error ("server");
92 }
93
94 function error_wrongpass () {
95     error ("wrongpass");
96 }
97
98 function error_unauthorized () {
99     error ("unauthorized");
100 }
101
102 function error_request () {
103     error ("request");
104 }
105
106 function error_file_too_big () {
107     error ("toobig");
108 }
109
110 function error_notanimage () {
111     error ("notimage");
112 }
113
114 function save_uploaded_file ($file, $con) {
115     $dest = "";
116     if (isset ($file) && ($file ["error"] != UPLOAD_ERR_NO_FILE)) {
117         img_check_upload ($file);
118         $dest = unique_file (UPLOADDIR, $file ["name"], $con);
119         if (!isset ($dest) || 
120                 (!move_uploaded_file ($file ["tmp_name"], $dest))) {
121             error_server ();
122         }
123         $mini_dest = getthumbsdir () . "/mini_" . basename_safe ($dest);
124
125         if (!create_thumbnail_or_copy ($dest, $mini_dest)) {
126             error_server ();
127         }
128     }
129     return basename_safe ($dest);
130 }
131
132 function img_check_upload ($file) {
133     if (!is_uploaded_file ($file ["tmp_name"])) {
134         if ($file ["error"] ==  UPLOAD_ERR_INI_SIZE) {
135             error_file_too_big ();
136         } else {
137             error_server ();
138         }
139     }
140     if (!getimagesize ($file ["tmp_name"])) {
141         error_notanimage ();
142     }
143 }
144
145 function delete_image_if_unused ($imgpath, $con) {
146     if (!isset ($imgpath) || (strlen ($imgpath) == 0)) {
147         return;
148     }
149     if ($con->imgpath_exists ($imgpath)) {
150         return;
151     }
152
153     $path = UPLOADDIR . "/" . $imgpath;
154     if (file_exists ($path)) {
155         unlink ($path);
156     }
157
158     $thumb_path = getthumbsdir () . "/mini_" . $imgpath;
159     if (file_exists ($thumb_path)) {
160         unlink ($thumb_path);
161     }
162 }
163
164 function unique_file ($dirname, $relpath, $con) {
165    $relpath = str_replace ('/', '', $relpath); // strip slashes from path
166    $relpath = str_replace ('\\', '', $relpath); // strip antislashes from path
167    $filename = $dirname . '/' . $relpath;
168    $counter = 1;
169
170    $dotpos = strrpos ($relpath, '.');
171    if ($dotpos) {
172        $base = substr ($relpath, 0, $dotpos);
173        $ext = substr ($relpath, $dotpos + 1);
174    } else {
175        $base = $relpath;
176        $ext = "";
177    }
178
179    while ($counter < 1000) {
180        if (!file_exists ($filename) && 
181            !($con->imgpath_exists (basename_safe ($filename)))) {
182            return $filename;
183        } else {
184             $counter++;
185             $filename = $dirname . '/' . $base . '_' . $counter . '.' . $ext;
186        }
187    }
188    // we tried to find an unused filename 1000 times. Give up now.
189    return null;
190 }
191
192 function setcookies ($user, $pwd) {
193     // cookie will be valid for 2 weeks. I've chosen that value
194     // arbitrarily, and it may change in the future.
195     $time = time () + 14 * 60 * 24 * 60;
196     if (version_compare (PHP_VERSION, '5.2.0', '>=')) {
197         setcookie (sprintf ("%sauth", DBPREFIX), md5 ($pwd), $time, "" , "", false, true);
198         setcookie (sprintf ("%suser", DBPREFIX), $user, $time, "" , "", false, true);
199     } else {
200         setcookie (sprintf ("%sauth", DBPREFIX), md5 ($pwd), $time, "" , "", false);
201         setcookie (sprintf ("%suser", DBPREFIX), $user, $time, "" , "", false);
202     }
203
204 }
205
206 function check_auth ($con, $user, $pwd, $auth_only) {
207     $authentificated = false;
208
209     if (isset ($pwd)) {
210         if ($con->checkpwdmd5 ($user, md5 ($pwd))) {
211             setcookies ($user, $pwd);
212             $authentificated = true;
213             if ($auth_only) {
214                 success_auth ($user);
215             }
216         } else {
217             error_unauthorized ();
218         }
219     }
220
221     if (!$authentificated && !($con->checkpwdmd5 (
222                              $_COOKIE [sprintf ("%suser",  DBPREFIX)],
223                              $_COOKIE [sprintf ("%sauth",  DBPREFIX)]))) {
224         error_unauthorized ();
225     }
226 }
227
228 function main ($con) {
229     if (!isset ($_POST ["request"])) {
230         error_request ();
231     }
232
233     $pwd = unquote ($_POST ["password"]);
234     $user = unquote ($_POST ["user"]);
235     // does user only want authentication or does he want to do other things
236     $auth_only = ($_POST ["request"] == "auth");
237     check_auth ($con, $user, $pwd, $auth_only);
238     if (!$user) {
239         $user = $_COOKIE [sprintf ("%suser",  DBPREFIX)];
240     }
241
242     switch ($_POST ["request"]) {
243         case "update":
244             $id = $_POST ["fid"];
245             $feature = $con->getfeature ($id);
246             if (!isset ($feature)) {
247                 error_unreferenced ($id);
248             }
249             if (($feature->user != $user) && ($user != "admin")) {
250                 error_unauthorized ();
251             }
252
253             // no file uploaded, but editor currently has an image: it means
254             // image was not changed
255             if ($_POST ["keep_img"] == "yes") {
256                 $imgpath = $feature->imgpath;
257             } else {
258                 $imgpath = save_uploaded_file ($_FILES ["image_file"], $con);
259             }
260
261             $lon = $_POST ["lon"];
262             $lat = $_POST ["lat"];
263             $title = unquote ($_POST ["title"]);
264             $description = unquote ($_POST ["description"]);
265
266             try {
267                 $new_feature = new feature ($id, $lon, $lat, $imgpath, $title, $description, 0, $user);
268             } catch (Exception $e) {
269                 error_request ();
270             }
271
272             if (($new_feature->lon == $feature->lon) &&
273                 ($new_feature->lat == $feature->lat) &&
274                 ($new_feature->title == $feature->title) &&
275                 ($new_feature->imgpath == $feature->imgpath) &&
276                 ($new_feature->description == $feature->description)) {
277                 error_nochange ($feature->id);
278             }
279
280             $old_imgpath = "";
281             if ($feature->imgpath && ($feature->imgpath != $new_feature->imgpath)) {
282                 $old_imgpath = $feature->imgpath;
283             }
284
285             try {
286                 $con->save_feature ($new_feature);
287             } catch (Exception $e) {
288                 error_server ();
289             }
290             if ($old_imgpath) {
291                 try {
292                     delete_image_if_unused ($old_imgpath, $con); 
293                 } catch (Exception $e) {}
294             }
295             success_feature ($new_feature, "update");
296         break;
297         case "add":
298             $imgpath = save_uploaded_file ($_FILES ["image_file"], $con);
299
300             $lon = $_POST ["lon"];
301             $lat = $_POST ["lat"];
302             $title = unquote ($_POST ["title"]);
303             $description = unquote ($_POST ["description"]);
304             try {
305                 $feature = new feature (null, $lon, $lat, $imgpath, $title, $description, 0, $user);
306             } catch (Exception $e) {
307                 error_request ();
308             }
309             try {
310                 $feature = $con->save_feature ($feature);
311             } catch (Exception $e) {
312                 error_server ();
313             }
314             success_feature ($feature, "add");
315         break;
316         case "del":
317             $id = $_POST ["fid"];
318             $feature = $con->getfeature ($id);
319             if (!isset ($feature)) {
320                 error_unreferenced ($id);
321             }
322             if ($feature->user != $user) {
323                 error_unauthorized ();
324             }
325             $imgpath = $feature->imgpath;
326
327             try {
328                 $con->delete_feature ($feature);
329             } catch (Exception $e) {
330                 error_server ();
331             }
332
333             try {
334                 delete_image_if_unused ($imgpath, $con);
335             } catch (Exception $e) {}
336
337             success_delete_feature ($feature);
338         case "changepass":
339             $currpass = unquote ($_POST ["pass_current"]);
340             if (!$con->checkpwdmd5 ($user, md5 ($currpass))) {
341                 error_wrongpass ();
342             }
343             $newpass = unquote ($_POST ["pass_new"]);
344             try {
345                 $con->setpwd ($user, $newpass);
346             } catch (Exception $e) {
347                 if ($e->getMessage () == anydbConnection::err_query) {
348                     error_request ();
349                 }
350                 error_server ();
351             }
352             setcookies ($user, $newpass);
353             success_changepass ($user);
354         break;
355         case "newuser":
356             if ($user != "admin") {
357                 error_unauthorized ();
358             }
359             $newuser_name = unquote ($_POST ["newuser_name"]);
360             if (!$newuser_name) {
361                 error_request ();
362             }
363             if ($con->user_exists ($newuser_name)) {
364                 error_newuser_exists ();
365             }
366             $newuser_password = unquote ($_POST ["newuser_password"]);
367             try {
368                 $con->setpwd ($newuser_name, $newuser_password);
369             } catch (Exception $e) {
370                 if ($e->getMessage () == anydbConnection::err_query) {
371                     error_request ();
372                 }
373                 error_server ();
374             }
375             success_newuser ($newuser_name);
376         break;
377         default:
378             error_request();
379         break;
380     }
381
382     error_server ();
383 }
384
385 if (!@include_once ("./inc/settings.php")) {
386     error_server ();
387 }
388 require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
389 require_once ("./inc/utils.php");
390
391 try {
392     $connection->connect (DBHOST, DBUSER, DBPWD, DBNAME, DBPREFIX);
393 } catch (Exception $e) {
394     error_server ();
395 }
396
397 main ($connection);
398 ?>