]> dev.renevier.net Git - syp.git/blob - api.php
images are stored on a ftp server
[syp.git] / api.php
1 <?php
2 /* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD
3    license. */
4
5 require_once ("./inc/settings.php");
6 require_once ("./inc/db/mysql.php");
7 require_once ("./inc/utils.php");
8
9 function exit_document ($body) {
10     exit ("<html><head></head><body>$body</body></html>");
11 }
12
13 function success_auth () {
14     success ("auth");
15 }
16
17 function success_feature ($feature, $request) {
18     $res = "<success request=\"$request\"><feature>";
19     $res .= "<id>" .  $feature->id .  "</id>";
20
21     $res .= "<imgurl>" .
22              ($feature->imgpath ? 
23                     full_url_from_imgpath ($feature->imgpath)
24                     : "") .
25              "</imgurl>";
26
27     $res .= "<description>" .
28                  htmlspecialchars ($feature->description) .
29                  "</description>";
30
31     // XXX: we do not use <title> because that would be interpreted and
32     // altered by browers html parser
33     $res .= "<heading>" . 
34             htmlspecialchars ($feature->title) .
35             "</heading>";
36
37     $res .= "<lon>" . $feature->lon . "</lon>";
38     $res .= "<lat>" . $feature->lat . "</lat>";
39     $res .= "</feature></success>";
40     exit_document ($res);
41 }
42
43 function success_delete_feature ($feature) {
44     $res = "<success request=\"del\"><feature>";
45     $res .= "<id>" .  $feature->id .  "</id>";
46     $res .= "</feature></success>";
47     exit_document ($res);
48 }
49
50 function success ($reason) {
51     exit_document ("<success request=\"$reason\"></success>");
52 }
53
54 function error ($reason) {
55     exit_document ("<error reason=\"$reason\"></error>");
56 }
57
58 function error_feature ($id, $reason) {
59     $res = "<error reason=\"$reason\"><feature>";
60     $res .= "<id>" .  $id .  "</id>";
61     $res .= "</feature></error>";
62     exit_document ($res);
63 }
64
65 function nochange_error ($id) {
66     error_feature ($id, "nochange");
67 }
68 function unreferenced_error ($id) {
69     error_feature ($id, "unreferenced");
70 }
71
72 function server_error () {
73     error ("server");
74 }
75
76 function unauthorized_error () {
77     error ("unauthorized");
78 }
79
80 function request_error () {
81     error ("request");
82 }
83
84 function file_too_big_error () {
85     error ("toobig");
86 }
87
88 function notanimage_error () {
89     error ("notimage");
90 }
91
92 function delete_from_ftp ($file) {
93     $ftp_conn = ftp_connect (FTPSERVER);
94     $login = ftp_login ($ftp_conn, FTPUSER, FTPPASS);
95     if ((!$ftp_conn) || (!$login)) {
96         server_error ();
97     }
98     $target = sprintf ("%s/%s", FTPIMGDIR, basename ($file));
99     $deleted = ftp_delete ($ftp_conn, $target);
100
101     if (!$deleted) {
102         server_error ();
103     }
104     ftp_close ($ftp_conn);
105 }
106
107 function send_to_ftp ($file) {
108     $ftp_conn = ftp_connect (FTPSERVER);
109     $login = ftp_login ($ftp_conn, FTPUSER, FTPPASS);
110     if ((!$ftp_conn) || (!$login)) {
111         server_error ();
112     }
113     $dest = sprintf ("%s/%s", FTPIMGDIR, basename ($file));
114     $upload = ftp_put ($ftp_conn, $dest, $file, FTP_BINARY);
115
116     if (!$upload) {
117         server_error ();
118     }
119     ftp_close ($ftp_conn);
120 }
121
122 function save_uploaded_file ($file, $con) {
123     $dest = "";
124     if (isset ($file) && ($file ["error"] != UPLOAD_ERR_NO_FILE)) {
125         img_check_upload ($file);
126         $dest = unique_file (UPLOADDIR, $file ["name"], $con);
127         if (!isset ($dest) || 
128                 (!move_uploaded_file ($file ["tmp_name"], $dest))) {
129             server_error ();
130         }
131         send_to_ftp ($dest);
132     }
133     return basename_safe ($dest);
134 }
135
136 function img_check_upload ($file) {
137     if (!is_uploaded_file ($file ["tmp_name"])) {
138         if ($file ["error"] ==  UPLOAD_ERR_INI_SIZE) {
139             file_too_big_error ();
140         } else {
141             server_error ();
142         }
143     }
144     if (!getimagesize ($file ["tmp_name"])) {
145         notanimage_error ();
146     }
147 }
148
149 function delete_image_if_unused ($imgpath, $con) {
150     if (!isset ($imgpath) || (strlen ($imgpath) == 0)) {
151         return;
152     }
153     if ($con->imgpath_exists ($imgpath)) {
154         return false;
155     }
156     $path = UPLOADDIR . "/" . $imgpath;
157     if (file_exists($path)) {
158         unlink ($path);
159         delete_from_ftp ($path);
160         return true;
161     } else {
162         return false;
163     }
164 }
165
166 function unique_file ($dirname, $relpath, $con) {
167    $relpath = str_replace ('/', '', $relpath); // strip slashes from path
168    $relpath = str_replace ('\\', '', $relpath); // strip antislashes from path
169    $filename = $dirname . '/' . $relpath;
170    $counter = 1;
171
172    $dotpos = strrpos ($relpath, '.');
173    if ($dotpos) {
174        $base = substr ($relpath, 0, $dotpos);
175        $ext = substr ($relpath, $dotpos + 1);
176    } else {
177        $base = $relpath;
178        $ext = "";
179    }
180
181    while ($counter < 1000) {
182        if (!file_exists ($filename) && 
183            !($con->imgpath_exists (basename_safe ($filename)))) {
184            return $filename;
185        } else {
186             $counter++;
187             $filename = $dirname . '/' . $base . '_' . $counter . '.' . $ext;
188        }
189    }
190    // we tried to find an unused filename 1000 times. Give up now.
191    return null;
192 }
193
194 function main ($con) {
195     if (!isset ($_POST ["request"])) {
196         request_error ();
197     }
198     if ($_POST ["request"] == "auth") {
199         $pwd = unquote ($_POST["password"]);
200         $user = "admin";
201         if ($con->checkpwdmd5 ($user, md5 ($pwd))) {
202             // cookie will be valid for 2 weeks. I've chosen that value
203             // arbitrarily, and it may change in the future.
204             $time = time () + 14 * 60 * 24 * 60;
205             $cookie_name = sprintf ("%sauth", DBPREFIX);
206             setcookie ($cookie_name, md5 ($pwd), $time, "" , "", false, true);
207             success_auth ();
208         } else {
209             unauthorized_error ();
210         }
211     }
212     if (!($con->checkpwdmd5 ("admin",
213                              $_COOKIE [sprintf ("%sauth", DBPREFIX)]))) {
214         unauthorized_error ();
215     }
216
217     switch ($_POST ["request"]) {
218         case "update":
219             $id = $_POST ["fid"];
220             $feature = $con->getfeature ($id);
221             if (!isset ($feature)) {
222                 unreferenced_error ($id);
223             }
224
225             // no file uploaded, but editor currently has an image: it means
226             // image was not changed
227             if ($_POST ["keep_img"] == "yes") {
228                 $imgpath = $feature->imgpath;
229             } else {
230                 $imgpath = save_uploaded_file ($_FILES ["image_file"], $con);
231             }
232
233             $lon = $_POST ["lon"];
234             $lat = $_POST ["lat"];
235             $title = unquote ($_POST ["title"]);
236             $description = unquote ($_POST ["description"]);
237
238             try {
239                 $new_feature = new feature ($id, $lon, $lat, $imgpath, $title, $description, 0);
240             } catch (Exception $e) {
241                 request_error ();
242             }
243
244             if (($new_feature->lon == $feature->lon) &&
245                 ($new_feature->lat == $feature->lat) &&
246                 ($new_feature->title == $feature->title) &&
247                 ($new_feature->imgpath == $feature->imgpath) &&
248                 ($new_feature->description == $feature->description)) {
249                 nochange_error ($feature->id);
250             }
251
252             $old_imgpath = "";
253             if ($feature->imgpath && ($feature->imgpath != $new_feature->imgpath)) {
254                 $old_imgpath = $feature->imgpath;
255             }
256
257             try {
258                 $con->save_feature ($new_feature);
259             } catch (Exception $e) {
260                 server_error ();
261             }
262             if ($old_imgpath) {
263                 try {
264                     delete_image_if_unused ($old_imgpath, $con); 
265                 } catch (Exception $e) {}
266             }
267             success_feature ($new_feature, "update");
268         break;
269         case "add":
270             $imgpath = save_uploaded_file ($_FILES ["image_file"], $con);
271
272             $lon = $_POST ["lon"];
273             $lat = $_POST ["lat"];
274             $title = unquote ($_POST ["title"]);
275             $description = unquote ($_POST ["description"]);
276             try {
277                 $feature = new feature (null, $lon, $lat, $imgpath, $title, $description, 0);
278             } catch (Exception $e) {
279                 request_error ();
280             }
281             try {
282                 $feature = $con->save_feature ($feature);
283             } catch (Exception $e) {
284                 server_error ();
285             }
286             success_feature ($feature, "add");
287         break;
288         case "del":
289             $id = $_POST ["fid"];
290             $feature = $con->getfeature ($id);
291             if (!isset ($feature)) {
292                 unreferenced_error ($id);
293             }
294             $imgpath = $feature->imgpath;
295
296             try {
297                 $con->delete_feature ($feature);
298             } catch (Exception $e) {
299                 server_error ();
300             }
301
302             try {
303                 delete_image_if_unused ($imgpath, $con);
304             } catch (Exception $e) {}
305
306             success_delete_feature ($feature);
307         default:
308             request_error();
309         break;
310     }
311
312     server_error ();
313 }
314
315 try {
316     $connection->connect (DBHOST, DBUSER, DBPWD, DBNAME, DBPREFIX);
317 } catch (Exception $e) {
318     server_error ();
319 }
320
321 main ($connection);
322 ?>