2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2007, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/types.h>
29 #include <curl/curl.h>
30 #include <curl/types.h>
31 #include <curl/easy.h>
34 #include <glib/gstdio.h>
37 #include "viktrwlayer.h"
38 #include "osm-traces.h"
40 #include "background.h"
43 * Login to use for OSM uploading.
45 static gchar
*user
= NULL
;
48 * Password to use for OSM uploading.
50 static gchar
*password
= NULL
;
53 * Mutex to protect auth. token
55 static GMutex
*login_mutex
= NULL
;
58 * Struct hosting needed info.
60 typedef struct _OsmTracesInfo
{
70 * Free an OsmTracesInfo struct.
72 static void oti_free(OsmTracesInfo
*oti
)
75 /* Fields have been g_strdup'ed */
76 g_free(oti
->name
); oti
->name
= NULL
;
77 g_free(oti
->description
); oti
->description
= NULL
;
78 g_free(oti
->tags
); oti
->tags
= NULL
;
79 g_free(oti
->track_name
); oti
->track_name
= NULL
;
81 g_object_unref(oti
->vtl
); oti
->vtl
= NULL
;
83 /* Main struct has been g_malloc'ed */
87 static void set_login(const gchar
*user_
, const gchar
*password_
)
90 if (login_mutex
== NULL
)
92 login_mutex
= g_mutex_new();
94 g_mutex_lock(login_mutex
);
95 g_free(user
); user
= NULL
;
96 g_free(password
); password
= NULL
;
97 user
= g_strdup(user_
);
98 password
= g_strdup(password_
);
99 g_mutex_unlock(login_mutex
);
102 static gchar
*get_login()
104 gchar
*user_pass
= NULL
;
105 g_mutex_lock(login_mutex
);
106 user_pass
= g_strdup_printf("%s:%s", user
, password
);
107 g_mutex_unlock(login_mutex
);
114 void osm_traces_upload_file(const char *user
,
115 const char *password
,
117 const char *filename
,
118 const char *description
,
124 char curl_error_buffer
[CURL_ERROR_SIZE
];
125 struct curl_slist
*headers
= NULL
;
126 struct curl_httppost
*post
=NULL
;
127 struct curl_httppost
*last
=NULL
;
128 gchar
*public_string
;
130 char *base_url
= "http://www.openstreetmap.org/api/0.4/gpx/create";
132 gchar
*user_pass
= get_login();
134 g_debug("%s: %s %s %s %s %s %s", __FUNCTION__
,
135 user
, password
, file
, filename
, description
, tags
);
138 curl
= curl_easy_init();
140 /* Filling the form */
141 curl_formadd(&post
, &last
,
142 CURLFORM_COPYNAME
, "description",
143 CURLFORM_COPYCONTENTS
, description
, CURLFORM_END
);
144 curl_formadd(&post
, &last
,
145 CURLFORM_COPYNAME
, "tags",
146 CURLFORM_COPYCONTENTS
, tags
, CURLFORM_END
);
151 curl_formadd(&post
, &last
,
152 CURLFORM_COPYNAME
, "public",
153 CURLFORM_COPYCONTENTS
, public_string
, CURLFORM_END
);
154 curl_formadd(&post
, &last
,
155 CURLFORM_COPYNAME
, "file",
157 CURLFORM_FILENAME
, filename
,
158 CURLFORM_CONTENTTYPE
, "text/xml", CURLFORM_END
);
160 /* Prepare request */
161 /* As explained in http://wiki.openstreetmap.org/index.php/User:LA2 */
162 /* Expect: header seems to produce incompatibilites between curl and httpd */
163 headers
= curl_slist_append(headers
, "Expect: ");
164 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, headers
);
165 curl_easy_setopt(curl
, CURLOPT_HTTPPOST
, post
);
166 curl_easy_setopt(curl
, CURLOPT_URL
, base_url
);
167 curl_easy_setopt(curl
, CURLOPT_USERPWD
, user_pass
);
168 curl_easy_setopt(curl
, CURLOPT_HTTPAUTH
, CURLAUTH_ANY
);
169 curl_easy_setopt(curl
, CURLOPT_ERRORBUFFER
, &curl_error_buffer
);
171 /* Execute request */
172 res
= curl_easy_perform(curl
);
176 res
= curl_easy_getinfo(curl
, CURLINFO_RESPONSE_CODE
, &code
);
179 g_debug("received valid curl response: %ld", code
);
181 g_warning("failed to upload data: HTTP response is %ld", code
);
184 g_error("curl_easy_getinfo failed: %d", res
);
188 g_warning("curl request failed: %s", curl_error_buffer
);
192 g_free(user_pass
); user_pass
= NULL
;
195 curl_easy_cleanup(curl
);
199 * uploading function executed by the background" thread
201 static void osm_traces_upload_thread ( OsmTracesInfo
*oti
, gpointer threaddata
)
204 gchar
*filename
= NULL
;
206 GError
*error
= NULL
;
209 g_assert(oti
!= NULL
);
211 /* Opening temporary file */
212 fd
= g_file_open_tmp("viking_osm_upload_XXXXXX.gpx", &filename
, &error
);
214 g_error("failed to open temporary file: %s", strerror(errno
));
217 g_clear_error(&error
);
218 g_debug("%s: temporary file = %s", __FUNCTION__
, filename
);
221 file
= fdopen(fd
, "w");
223 /* writing gpx file */
224 if (oti
->track_name
!= NULL
)
226 /* Upload only the selected track */
227 VikTrack
*track
= vik_trw_layer_get_track(oti
->vtl
, oti
->track_name
);
228 a_gpx_write_track_file(oti
->track_name
, track
, file
);
231 /* Upload the whole VikTrwLayer */
232 a_gpx_write_file(oti
->vtl
, file
);
234 /* We can close the file */
235 /* This also close the associated fd */
238 /* finally, upload it */
239 osm_traces_upload_file(user
, password
, filename
,
240 oti
->name
, oti
->description
, oti
->tags
, oti
->public);
242 /* Removing temporary file */
243 ret
= g_unlink(filename
);
245 g_error("failed to unlink temporary file: %s", strerror(errno
));
250 * Uploading a VikTrwLayer
252 * @param vtl VikTrwLayer
253 * @param track_name if not null, the name of the track to upload
255 static void osm_traces_upload_viktrwlayer ( VikTrwLayer
*vtl
, const gchar
*track_name
)
257 GtkWidget
*dia
= gtk_dialog_new_with_buttons ("OSM upload",
258 VIK_GTK_WINDOW_FROM_LAYER(vtl
),
259 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
266 const gchar
*name
= NULL
;
267 GtkWidget
*user_label
, *user_entry
;
268 GtkWidget
*password_label
, *password_entry
;
269 GtkWidget
*name_label
, *name_entry
;
270 GtkWidget
*description_label
, *description_entry
;
271 GtkWidget
*tags_label
, *tags_entry
;
273 GtkTooltips
* dialog_tips
;
275 dialog_tips
= gtk_tooltips_new();
277 user_label
= gtk_label_new("Email:");
278 user_entry
= gtk_entry_new();
280 gtk_entry_set_text(GTK_ENTRY(user_entry
), user
);
281 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), user_label
, FALSE
, FALSE
, 0);
282 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), user_entry
, FALSE
, FALSE
, 0);
283 gtk_widget_show_all ( user_label
);
284 gtk_widget_show_all ( user_entry
);
285 gtk_tooltips_set_tip (dialog_tips
, user_entry
,
286 "The email used as login",
287 "Enter the email you use to login into www.openstreetmap.org.");
289 password_label
= gtk_label_new("Password:");
290 password_entry
= gtk_entry_new();
291 if (password
!= NULL
)
292 gtk_entry_set_text(GTK_ENTRY(password_entry
), password
);
293 /* This is a password -> invisible */
294 gtk_entry_set_visibility(GTK_ENTRY(password_entry
), FALSE
);
295 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), password_label
, FALSE
, FALSE
, 0);
296 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), password_entry
, FALSE
, FALSE
, 0);
297 gtk_widget_show_all ( password_label
);
298 gtk_widget_show_all ( password_entry
);
299 gtk_tooltips_set_tip (dialog_tips
, password_entry
,
300 "The password used to login",
301 "Enter the password you use to login into www.openstreetmap.org.");
303 name_label
= gtk_label_new("File's name:");
304 name_entry
= gtk_entry_new();
305 if (track_name
!= NULL
)
308 name
= vik_layer_get_name(VIK_LAYER(vtl
));
309 gtk_entry_set_text(GTK_ENTRY(name_entry
), name
);
310 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), name_label
, FALSE
, FALSE
, 0);
311 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), name_entry
, FALSE
, FALSE
, 0);
312 gtk_widget_show_all ( name_label
);
313 gtk_widget_show_all ( name_entry
);
314 gtk_tooltips_set_tip (dialog_tips
, name_entry
,
315 "The name of the file on OSM",
316 "This is the name of the file created on the server. "
317 "This is not the name of the local file.");
319 description_label
= gtk_label_new("Description:");
320 description_entry
= gtk_entry_new();
321 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), description_label
, FALSE
, FALSE
, 0);
322 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), description_entry
, FALSE
, FALSE
, 0);
323 gtk_widget_show_all ( description_label
);
324 gtk_widget_show_all ( description_entry
);
325 gtk_tooltips_set_tip (dialog_tips
, description_entry
,
326 "The description of the trace",
329 tags_label
= gtk_label_new("Tags:");
330 tags_entry
= gtk_entry_new();
331 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), tags_label
, FALSE
, FALSE
, 0);
332 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), tags_entry
, FALSE
, FALSE
, 0);
333 gtk_widget_show_all ( tags_label
);
334 gtk_widget_show_all ( tags_entry
);
335 gtk_tooltips_set_tip (dialog_tips
, tags_entry
,
336 "The tags associated to the trace",
339 public = gtk_check_button_new_with_label("Public");
340 /* Set public by default */
341 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(public), TRUE
);
342 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia
)->vbox
), public, FALSE
, FALSE
, 0);
343 gtk_widget_show_all ( public );
344 gtk_tooltips_set_tip (dialog_tips
, public,
345 "Indicates if the trace is public or not",
348 if ( gtk_dialog_run ( GTK_DIALOG(dia
) ) == GTK_RESPONSE_ACCEPT
)
352 /* overwrite authentication info */
353 set_login(gtk_entry_get_text(GTK_ENTRY(user_entry
)),
354 gtk_entry_get_text(GTK_ENTRY(password_entry
)));
356 /* Storing data for the future thread */
357 OsmTracesInfo
*info
= g_malloc(sizeof(OsmTracesInfo
));
358 info
->name
= g_strdup(gtk_entry_get_text(GTK_ENTRY(name_entry
)));
359 info
->description
= g_strdup(gtk_entry_get_text(GTK_ENTRY(description_entry
)));
360 /* TODO Normalize tags: they will be used as URL part */
361 info
->tags
= g_strdup(gtk_entry_get_text(GTK_ENTRY(tags_entry
)));
362 info
->public = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(public));
363 info
->vtl
= VIK_TRW_LAYER(g_object_ref(vtl
));
364 info
->track_name
= (track_name
== NULL
) ? NULL
: g_strdup(track_name
);
366 title
= g_strdup_printf("Uploading %s to OSM", info
->name
);
368 /* launch the thread */
369 a_background_thread(VIK_GTK_WINDOW_FROM_LAYER(vtl
), /* parent window */
370 title
, /* description string */
371 (vik_thr_func
) osm_traces_upload_thread
, /* function to call within thread */
372 info
, /* pass along data */
373 (vik_thr_free_func
) oti_free
, /* function to free pass along data */
374 (vik_thr_free_func
) NULL
,
376 g_free ( title
); title
= NULL
;
378 gtk_widget_destroy ( dia
);
382 * Function called by the entry menu of a TrwLayer
384 void osm_traces_upload_cb ( gpointer layer_and_vlp
[2], guint file_type
)
386 osm_traces_upload_viktrwlayer(VIK_TRW_LAYER(layer_and_vlp
[0]), NULL
);
390 * Function called by the entry menu of a single track
392 void osm_traces_upload_track_cb ( gpointer pass_along
[6] )
394 osm_traces_upload_viktrwlayer(VIK_TRW_LAYER(pass_along
[0]), pass_along
[3]);