1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21 #include <stdlib.h>
22 #define __USE_POSIX
23 #include <time.h>
24 #include <glib/gstdio.h>
25
26 #include "applet-struct.h"
27 #include "applet-dnd2share.h"
28
29
cd_dnd2share_free_uploaded_item(CDUploadedItem * pItem)30 void cd_dnd2share_free_uploaded_item (CDUploadedItem *pItem)
31 {
32 if (pItem == NULL)
33 return ;
34 g_strfreev (pItem->cDistantUrls);
35 g_free (pItem->cItemName);
36 g_free (pItem->cLocalPath);
37 g_free (pItem);
38 }
39
40
_get_short_text_for_menu(const gchar * cInitText)41 static gchar * _get_short_text_for_menu (const gchar *cInitText)
42 {
43 if (cInitText == NULL) // the backend should not allow that!
44 return g_strdup (D_("No text"));
45
46 // remove extras withespaces first
47 gchar *cLongText = g_strstrip (g_strdup (cInitText));
48 // then print only the first line => no, like Clipper
49 /*gchar *str = strchr (cLongText, '\n');
50 if (str)
51 *str = '\0';*/
52 gchar *cShortText = cairo_dock_cut_string (cLongText, 40);
53
54 // With 'Text' label, it's different than filename
55 gchar *cResult = g_strdup_printf ("%s %s", D_("Text:"), cShortText);
56
57 g_free (cLongText);
58 g_free (cShortText);
59
60 return cResult;
61 }
62
cd_dnd2share_build_history(void)63 void cd_dnd2share_build_history (void)
64 {
65 gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
66 GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
67 g_free (cConfFilePath);
68 if (pKeyFile == NULL) // no history yet.
69 return ;
70
71 gsize length = 0;
72 gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
73 if (pGroupList == NULL)
74 return ;
75
76 CDUploadedItem *pItem;
77 int iSiteID, iFileType;
78 gchar *cItemName;
79 GString *sUrlKey = g_string_new ("");
80 GError *erreur = NULL;
81 int i,j;
82 for (i = 0; pGroupList[i] != NULL; i ++)
83 {
84 cItemName = pGroupList[i];
85 iSiteID = g_key_file_get_integer (pKeyFile, cItemName, "site", &erreur);
86 if (erreur != NULL)
87 {
88 cd_warning (erreur->message);
89 g_error_free (erreur);
90 erreur = NULL;
91 g_free (cItemName);
92 continue;
93 }
94 if (iSiteID >= CD_NB_SITES_MAX)
95 {
96 cd_warning ("dnd2share : this backend doesn't exist !");
97 g_free (cItemName);
98 continue;
99 }
100 iFileType = g_key_file_get_integer (pKeyFile, cItemName, "type", &erreur);
101 if (erreur != NULL)
102 {
103 cd_warning (erreur->message);
104 g_error_free (erreur);
105 erreur = NULL;
106 g_free (cItemName);
107 continue;
108 }
109 if (iFileType >= CD_NB_FILE_TYPES)
110 {
111 cd_warning ("dnd2share : this type of file doesn't exist !");
112 g_free (cItemName);
113 continue;
114 }
115
116 pItem = g_new0 (CDUploadedItem, 1);
117 pItem->cItemName = cItemName;
118 pItem->iSiteID = iSiteID;
119 pItem->iFileType = iFileType;
120 pItem->cDistantUrls = g_new0 (gchar*, myData.backends[iFileType][iSiteID].iNbUrls+1);
121 for (j = 0; j < myData.backends[iFileType][iSiteID].iNbUrls; j ++)
122 {
123 g_string_printf (sUrlKey, "url%d", j);
124 pItem->cDistantUrls[j] = g_key_file_get_string (pKeyFile, cItemName, sUrlKey->str, NULL); // NULL if this URL has not been saved before.
125 }
126 pItem->iDate = g_key_file_get_integer (pKeyFile, cItemName, "date", NULL);
127
128 pItem->cLocalPath = g_key_file_get_string (pKeyFile, cItemName, "local path", NULL);
129 if (pItem->iFileType == CD_TYPE_TEXT)
130 pItem->cFileName = _get_short_text_for_menu (pItem->cLocalPath);
131 else
132 pItem->cFileName = g_path_get_basename (pItem->cLocalPath);
133
134 myData.pUpoadedItems = g_list_prepend (myData.pUpoadedItems, pItem);
135 }
136 g_string_free (sUrlKey, TRUE);
137 g_free (pGroupList); // the content has been added in the list.
138 g_key_file_free (pKeyFile);
139 }
140
cd_dnd2share_clear_history(void)141 void cd_dnd2share_clear_history (void)
142 {
143 g_list_foreach (myData.pUpoadedItems, (GFunc) cd_dnd2share_free_uploaded_item, NULL);
144 g_list_free (myData.pUpoadedItems);
145 myData.pUpoadedItems = NULL;
146 }
147
148
149
_cd_dnd2share_threaded_upload(CDSharedMemory * pSharedMemory)150 static void _cd_dnd2share_threaded_upload (CDSharedMemory *pSharedMemory)
151 {
152 gchar *cFilePath = pSharedMemory->cCurrentFilePath;
153
154 pSharedMemory->cResultUrls = g_new0 (gchar *, pSharedMemory->iNbUrls+1); // NULL-terminated
155 pSharedMemory->upload (cFilePath, pSharedMemory->cLocalDir, pSharedMemory->bAnonymous, pSharedMemory->iLimitRate, pSharedMemory->cResultUrls, &pSharedMemory->pError);
156
157 if (pSharedMemory->cResultUrls[0] && pSharedMemory->iTinyURLService != 0) // tiny-url.
158 {
159 gchar *Command = NULL;
160 switch (pSharedMemory->iTinyURLService)
161 {
162 case 1:
163 default:
164 Command = g_strdup_printf ("http://tinyurl.com/api-create.php?url=%s", pSharedMemory->cResultUrls[0]);
165 break;
166 case 2:
167 Command = g_strdup_printf ("http://shorterlink.org/createlink.php?url=%s", pSharedMemory->cResultUrls[0]);
168 break;
169 /*http://soso.bz/
170 http://notlong.com/links/
171 http://www.minu.me/
172 http://cuturl.biz/
173 http://tiny.cc/
174 http://o-x.fr/create.php
175 http://petitlien.fr/create.php
176 http://bit.ly
177 http://is.gd/create.php*/
178 }
179 pSharedMemory->cResultUrls[pSharedMemory->iNbUrls-1] = cairo_dock_get_url_data (Command, NULL);
180 g_free (Command);
181 }
182 }
183
_cd_dnd2share_show_error_dialog(const gchar * cError)184 static void _cd_dnd2share_show_error_dialog (const gchar *cError)
185 {
186 gldi_dialogs_remove_on_icon (myIcon);
187
188 gldi_dialog_show_temporary_with_icon (cError,
189 myIcon,
190 myContainer,
191 myConfig.dTimeDialogs * 2,
192 MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
193 }
194
_cd_dnd2share_update_from_result(CDSharedMemory * pSharedMemory)195 static gboolean _cd_dnd2share_update_from_result (CDSharedMemory *pSharedMemory)
196 {
197 CD_APPLET_ENTER;
198 gchar *cFilePath = pSharedMemory->cCurrentFilePath;
199 if (pSharedMemory->pError != NULL)
200 _cd_dnd2share_show_error_dialog (pSharedMemory->pError->message);
201 else if (pSharedMemory->cResultUrls == NULL || pSharedMemory->cResultUrls[0] == NULL) // just to be sure
202 _cd_dnd2share_show_error_dialog (DND2SHARE_GENERIC_ERROR_MSG);
203 else
204 {
205 CDSiteBackend *pCurrentBackend = myData.pCurrentBackend[pSharedMemory->iCurrentFileType];
206 // we add it in the history.
207 if (myConfig.iNbItems != 0)
208 {
209 // open the file which contains the history
210 gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
211 GKeyFile *pKeyFile;
212 if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS)) // no history yet.
213 pKeyFile = g_key_file_new ();
214 else
215 pKeyFile = cairo_dock_open_key_file (cConfFilePath);
216 if (pKeyFile == NULL) // probleme de droit ?
217 {
218 cd_warning ("Couldn't add this item to history.");
219 }
220 else
221 {
222 // we check the size limit
223 gsize length = 0;
224 gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
225 if (length == myConfig.iNbItems) // if yes, we remove the first entry
226 {
227 g_key_file_remove_group (pKeyFile, pGroupList[0], NULL);
228 if (myData.pUpoadedItems != NULL) // which is the last one in the list
229 {
230 GList *it = g_list_last (myData.pUpoadedItems);
231 if (it->prev != NULL)
232 it->prev->next = NULL;
233 it->prev = NULL;
234 cd_dnd2share_free_uploaded_item (it->data);
235 g_list_free1 (it);
236 }
237 }
238 g_strfreev (pGroupList);
239
240 // we add the new item at the end of the file
241 time_t iDate = time (NULL);
242 gchar *cItemName = g_strdup_printf ("item_%ld", iDate);
243
244 g_key_file_set_integer (pKeyFile, cItemName, "site", myConfig.iPreferedSite[pSharedMemory->iCurrentFileType]);
245 g_key_file_set_integer (pKeyFile, cItemName, "date", iDate);
246 g_key_file_set_integer (pKeyFile, cItemName, "type", pSharedMemory->iCurrentFileType);
247 GString *sUrlKey = g_string_new ("");
248 int j;
249 for (j = 0; j < pCurrentBackend->iNbUrls; j ++)
250 {
251 g_string_printf (sUrlKey, "url%d", j);
252 g_key_file_set_string (pKeyFile, cItemName, sUrlKey->str, pSharedMemory->cResultUrls[j]);
253 }
254 g_key_file_set_string (pKeyFile, cItemName, "local path", cFilePath);
255
256 // and at the beginning of the list
257 CDUploadedItem *pItem = g_new0 (CDUploadedItem, 1);
258 pItem->cItemName = cItemName;
259 pItem->iSiteID = myConfig.iPreferedSite[pSharedMemory->iCurrentFileType];
260 pItem->iFileType = pSharedMemory->iCurrentFileType;
261 pItem->cDistantUrls = g_new0 (gchar*, pCurrentBackend->iNbUrls + 1);
262 for (j = 0; j < pCurrentBackend->iNbUrls; j ++)
263 {
264 pItem->cDistantUrls[j] = g_strdup (pSharedMemory->cResultUrls[j]);
265 }
266 pItem->iDate = iDate;
267 pItem->cLocalPath = g_strdup (cFilePath);
268 if (pItem->iFileType == CD_TYPE_TEXT)
269 pItem->cFileName = _get_short_text_for_menu (cFilePath);
270 else
271 pItem->cFileName = g_path_get_basename (cFilePath);
272 myData.pUpoadedItems = g_list_prepend (myData.pUpoadedItems, pItem);
273
274 // We flush the file.
275 cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
276 g_key_file_free (pKeyFile);
277 g_string_free (sUrlKey, TRUE);
278
279 // we keep a copy if it's an image
280 if (myConfig.bkeepCopy && pSharedMemory->iCurrentFileType == CD_TYPE_IMAGE)
281 {
282 gchar *cCommand = g_strdup_printf ("cp '%s' '%s/%s'", cFilePath, myData.cWorkingDirPath, cItemName);
283 int r = system (cCommand);
284 if (r < 0)
285 cd_warning ("Not able to launch this command: %s", cCommand);
286 g_free (cCommand);
287 }
288 }
289 g_free (cConfFilePath);
290 }
291
292 // We copy the url to the clipboard
293 gchar *cURL = NULL;
294 if (myConfig.bUseTinyAsDefault)
295 cURL = pSharedMemory->cResultUrls[pCurrentBackend->iNbUrls-1];
296 if (cURL == NULL)
297 cURL = pSharedMemory->cResultUrls[pCurrentBackend->iPreferedUrlType];
298 if (cURL == NULL)
299 {
300 int i;
301 for (i = 0; i < pCurrentBackend->iNbUrls && cURL == NULL; i ++)
302 {
303 cURL = pSharedMemory->cResultUrls[i];
304 }
305 }
306 cd_dnd2share_copy_url_to_clipboard (cURL);
307
308 // we keep the last URL if we don't want the history.
309 g_free (myData.cLastURL);
310 myData.cLastURL = g_strdup (cURL);
311 myData.iCurrentItemNum = 0;
312
313 // we can now display a dialogue.
314 if (myConfig.bEnableDialogs || myDesklet)
315 {
316 gldi_dialogs_remove_on_icon (myIcon);
317 gldi_dialog_show_temporary_with_icon (D_("File has been uploaded.\nJust press CTRL+v to paste its URL anywhere."),
318 myIcon,
319 myContainer,
320 myConfig.dTimeDialogs,
321 MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
322 }
323
324 // and set the image on the icon.
325 if (myConfig.bDisplayLastImage)
326 {
327 if (pSharedMemory->iCurrentFileType == CD_TYPE_IMAGE)
328 CD_APPLET_SET_IMAGE_ON_MY_ICON (cFilePath);
329 else
330 CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
331 }
332 }
333
334 // stop the animation.
335 CD_APPLET_STOP_DEMANDING_ATTENTION;
336
337 // delete the file if it was a temporary one.
338 if (pSharedMemory->bTempFile)
339 {
340 g_remove (pSharedMemory->cCurrentFilePath);
341 }
342
343 if (myData.cTmpFilePath != NULL)
344 {
345 g_remove (myData.cTmpFilePath);
346 g_free (myData.cTmpFilePath);
347 myData.cTmpFilePath = NULL;
348 }
349
350 gldi_task_discard (myData.pTask);
351 myData.pTask = NULL;
352 CD_APPLET_LEAVE (FALSE);
353 }
_free_shared_memory(CDSharedMemory * pSharedMemory)354 static void _free_shared_memory (CDSharedMemory *pSharedMemory)
355 {
356 g_free (pSharedMemory->cLocalDir);
357 g_free (pSharedMemory->cCurrentFilePath);
358 g_strfreev (pSharedMemory->cResultUrls);
359 if (pSharedMemory->pError != NULL)
360 g_error_free (pSharedMemory->pError);
361 g_free (pSharedMemory);
362 }
363 #define CD_BUFFER_LENGTH 50
cd_dnd2share_launch_upload(const gchar * cFilePath,CDFileType iFileType)364 void cd_dnd2share_launch_upload (const gchar *cFilePath, CDFileType iFileType)
365 {
366 if (myData.pTask != NULL)
367 {
368 cd_warning ("Please wait the current upload is finished before starting a new one.");
369 gldi_dialogs_remove_on_icon (myIcon);
370 gldi_dialog_show_temporary_with_icon (D_("Please wait for the current upload to finish before starting a new one."),
371 myIcon,
372 myContainer,
373 myConfig.dTimeDialogs,
374 MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
375 return ;
376 }
377
378 if (myData.pCurrentBackend[iFileType]->upload == NULL)
379 {
380 cd_warning ("sorry, it's still not possible to upload this type of file");
381 return ;
382 }
383
384 // launch the task.
385 CDSharedMemory *pSharedMemory = g_new0 (CDSharedMemory, 1);
386 gboolean bIsPath = FALSE; // we can receive text or a text file
387 if (strncmp (cFilePath, "file://", 7) == 0)
388 {
389 cd_debug ("FilePath: %s", cFilePath);
390 cFilePath += 7;
391 bIsPath = TRUE;
392 }
393 else if (iFileType == CD_TYPE_TEXT && *cFilePath == '/' && g_file_test (cFilePath, G_FILE_TEST_EXISTS))
394 bIsPath = TRUE;
395
396 gchar *cTmpFile = NULL;
397 if (myConfig.bUseOnlyFileType)
398 {
399 // for a piece of text, write it in a temporary file and upload this one.
400 if (iFileType == CD_TYPE_TEXT && ! bIsPath)
401 {
402 // make a filename based on the upload date.
403 cTmpFile = g_new0 (gchar, CD_BUFFER_LENGTH+1);
404 time_t epoch = time (NULL);
405 struct tm currentTime;
406 localtime_r (&epoch, ¤tTime);
407 strftime (cTmpFile, CD_BUFFER_LENGTH, "/tmp/cd-%F__%H-%M-%S.txt", ¤tTime);
408
409 // write the text inside.
410 g_file_set_contents (cTmpFile,
411 cFilePath,
412 -1,
413 NULL);
414
415 // upload this file
416 cFilePath = cTmpFile;
417 pSharedMemory->bTempFile = TRUE;
418 }
419 // force the 'file' type to be used.
420 pSharedMemory->iCurrentFileType = CD_TYPE_FILE;
421 }
422 else
423 {
424 pSharedMemory->iCurrentFileType = iFileType;
425 }
426
427 // If we drop a text file, we have an URI but we want to post the content to a website
428 if (pSharedMemory->iCurrentFileType == CD_TYPE_TEXT && bIsPath)
429 {
430 cd_debug ("Type is text and it's a file: %s", cFilePath);
431 gchar *cContents = NULL;
432 gsize iLength;
433 g_file_get_contents (cFilePath, &cContents, &iLength, NULL);
434 if (cContents == NULL) // file was not readable, abort.
435 {
436 cd_warning ("file not readable !");
437 gldi_dialogs_remove_on_icon (myIcon);
438 gldi_dialog_show_temporary_with_icon (D_("This file is not readable."),
439 myIcon,
440 myContainer,
441 myConfig.dTimeDialogs,
442 MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
443 return ;
444 }
445 pSharedMemory->cCurrentFilePath = cContents;
446 }
447 else
448 pSharedMemory->cCurrentFilePath = g_strdup (cFilePath);
449
450 g_free (cTmpFile);
451
452 pSharedMemory->iTinyURLService = myConfig.iTinyURLService;
453 pSharedMemory->cLocalDir = g_strdup (myConfig.cLocalDir);
454 pSharedMemory->bAnonymous = myConfig.bAnonymous;
455 pSharedMemory->iLimitRate = myConfig.iLimitRate;
456
457 CDSiteBackend *pCurrentBackend = myData.pCurrentBackend[pSharedMemory->iCurrentFileType];
458 g_return_if_fail (pCurrentBackend != NULL);
459 pSharedMemory->upload = pCurrentBackend->upload;
460 pSharedMemory->iNbUrls = pCurrentBackend->iNbUrls;
461
462 myData.pTask = gldi_task_new_full (0, // 1 shot task.
463 (GldiGetDataAsyncFunc) _cd_dnd2share_threaded_upload,
464 (GldiUpdateSyncFunc) _cd_dnd2share_update_from_result,
465 (GFreeFunc) _free_shared_memory,
466 pSharedMemory);
467
468 gldi_task_launch (myData.pTask);
469
470 CD_APPLET_DEMANDS_ATTENTION (myConfig.cIconAnimation, 1e6); // we'll stop it later, at the end of the upload.
471 }
472
473
474
cd_dnd2share_clear_working_directory(void)475 void cd_dnd2share_clear_working_directory (void)
476 {
477 g_return_if_fail (myData.cWorkingDirPath != NULL && *myData.cWorkingDirPath == '/');
478 gchar *cCommand = g_strdup_printf ("rm -rf '%s'/*", myData.cWorkingDirPath);
479 int r = system (cCommand);
480 if (r < 0)
481 cd_warning ("Not able to launch this command: %s", cCommand);
482 g_free (cCommand);
483
484 gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
485 g_file_set_contents (cConfFilePath, "#dnd2share's history\n\n", -1, NULL);
486 g_free (cConfFilePath);
487
488 if (myConfig.bDisplayLastImage)
489 {
490 CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
491 }
492 }
493
494
cd_dnd2share_clear_copies_in_working_directory(void)495 void cd_dnd2share_clear_copies_in_working_directory (void)
496 {
497 g_return_if_fail (myData.cWorkingDirPath != NULL && *myData.cWorkingDirPath == '/');
498 gchar *cCommand = g_strdup_printf ("find '%s' -mindepth 1 ! -name *.conf -exec rm -f '{}' \\;", myData.cWorkingDirPath);
499 int r = system (cCommand);
500 if (r < 0)
501 cd_warning ("Not able to launch this command: %s", cCommand);
502 g_free (cCommand);
503 }
504
cd_dnd2share_set_working_directory_size(guint iNbItems)505 void cd_dnd2share_set_working_directory_size (guint iNbItems)
506 {
507 gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
508 GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
509 if (pKeyFile == NULL) // no history yet
510 {
511 g_free (cConfFilePath);
512 return ;
513 }
514
515 gsize length = 0;
516 gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
517 if (length > iNbItems)
518 {
519 gchar *cItemName;
520 GString *sPreviewPath = g_string_new ("");
521 guint i;
522 for (i = 0; pGroupList[i] != NULL && i < length - iNbItems; i ++) // we remove all extras groups and the preview
523 {
524 cItemName = pGroupList[i];
525 g_string_printf (sPreviewPath, "%s/%s", myData.cWorkingDirPath, cItemName);
526 g_remove (sPreviewPath->str);
527 g_key_file_remove_group (pKeyFile, cItemName, NULL);
528 }
529 cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
530 g_string_free (sPreviewPath, TRUE);
531 }
532
533 g_strfreev (pGroupList);
534 g_key_file_free (pKeyFile);
535 g_free (cConfFilePath);
536 }
537
cd_dnd2share_clean_working_directory(void)538 void cd_dnd2share_clean_working_directory (void)
539 {
540 if (myConfig.iNbItems == 0) // no more history => clean the working directory.
541 {
542 cd_debug ("DND2SHARE : Pas d'historique -> On efface le contenu de '%s'", myData.cWorkingDirPath);
543 cd_dnd2share_clear_working_directory ();
544 }
545 else
546 {
547 cd_dnd2share_set_working_directory_size (myConfig.iNbItems); // we remove extras items.
548 if (! myConfig.bkeepCopy) // we don't want a copy of the images
549 {
550 cd_debug ("DND2SHARE : Pas de copies locales -> On efface les images de '%s'", myData.cWorkingDirPath);
551 cd_dnd2share_clear_copies_in_working_directory ();
552 }
553 }
554 }
555
556
cd_dnd2share_copy_url_to_clipboard(const gchar * cURL)557 void cd_dnd2share_copy_url_to_clipboard (const gchar *cURL)
558 {
559 GtkClipboard *pClipBoard;
560 pClipBoard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
561 gtk_clipboard_set_text (pClipBoard, cURL, -1);
562 }
cd_dnd2share_copy_url_to_primary(const gchar * cURL)563 void cd_dnd2share_copy_url_to_primary (const gchar *cURL)
564 {
565 GtkClipboard *pClipBoard;
566 pClipBoard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
567 gtk_clipboard_set_text (pClipBoard, cURL, -1);
568 }
569
cd_dnd2share_get_prefered_url_from_item(CDUploadedItem * pItem)570 gchar *cd_dnd2share_get_prefered_url_from_item (CDUploadedItem *pItem)
571 {
572 CDSiteBackend *pBackend = &myData.backends[pItem->iFileType][pItem->iSiteID];
573 //g_print ("%s (type:%d; site:%d)\n", __func__, pItem->iFileType, pItem->iSiteID);
574 gchar *cURL = NULL;
575 if (myConfig.bUseTinyAsDefault)
576 cURL = pItem->cDistantUrls[pBackend->iNbUrls-1];
577 if (cURL == NULL)
578 cURL = pItem->cDistantUrls[pBackend->iPreferedUrlType];
579 if (cURL == NULL)
580 {
581 int i;
582 for (i = 0; i < pBackend->iNbUrls && cURL == NULL; i ++)
583 {
584 cURL = pItem->cDistantUrls[i];
585 }
586 }
587 return cURL;
588 }
589
cd_dnd2share_set_current_url_from_item(CDUploadedItem * pItem)590 void cd_dnd2share_set_current_url_from_item (CDUploadedItem *pItem)
591 {
592 gchar *cURL = cd_dnd2share_get_prefered_url_from_item (pItem);
593 g_free (myData.cLastURL);
594 myData.cLastURL = g_strdup (cURL);
595
596 int i = 0;
597 GList *it;
598 for (it = myData.pUpoadedItems; it != NULL; it = it->next)
599 {
600 if (it->data == pItem)
601 break ;
602 i ++;
603 }
604 myData.iCurrentItemNum = i;
605 }
606
607
cd_dnd2share_remove_one_item(CDUploadedItem * pItem)608 void cd_dnd2share_remove_one_item (CDUploadedItem *pItem)
609 {
610 g_return_if_fail (pItem != NULL);
611
612 // we remove the corresponding group in the history file
613 gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
614 if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS)) // no history yet.
615 return;
616
617 GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
618 if (pKeyFile == NULL) // right problem?
619 {
620 cd_warning ("Couldn't remove this item from history.");
621 return ;
622 }
623
624 g_key_file_remove_group (pKeyFile, pItem->cItemName, NULL);
625 cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
626 g_key_file_free (pKeyFile);
627 g_free (cConfFilePath);
628
629 // we remove the local copy.
630 gchar *cPreviewPath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, pItem->cItemName);
631 g_remove (cPreviewPath);
632 g_free (cPreviewPath);
633
634 // If it's the current item, switch to the next one.
635 if (myData.pUpoadedItems && myData.pUpoadedItems->data == pItem)
636 {
637 g_free (myData.cLastURL);
638 myData.cLastURL = NULL;
639 myData.iCurrentItemNum = 0;
640 if (myData.pUpoadedItems->next != NULL)
641 {
642 CDUploadedItem *pNextItem = myData.pUpoadedItems->next->data;
643 gchar *cURL = cd_dnd2share_get_prefered_url_from_item (pNextItem);
644 myData.cLastURL = g_strdup (cURL);
645 }
646 }
647
648 // We remove the item from the list
649 myData.pUpoadedItems = g_list_remove (myData.pUpoadedItems, pItem);
650 cd_dnd2share_free_uploaded_item (pItem);
651 }
652
653
cd_dnd2share_register_new_backend(CDFileType iFileType,const gchar * cSiteName,int iNbUrls,const gchar ** cUrlLabels,int iPreferedUrlType,CDUploadFunc pUploadFunc)654 void cd_dnd2share_register_new_backend (CDFileType iFileType, const gchar *cSiteName, int iNbUrls, const gchar **cUrlLabels, int iPreferedUrlType, CDUploadFunc pUploadFunc)
655 {
656 int iNumSite = myData.iNbSitesForType[iFileType];
657 CDSiteBackend *pNewBackend = &myData.backends[iFileType][iNumSite];
658 myData.iNbSitesForType[iFileType] ++;
659
660 pNewBackend->cSiteName = cSiteName;
661 pNewBackend->iNbUrls = iNbUrls + 1; // +1 for tiny-url.
662 pNewBackend->cUrlLabels = g_new0 (gchar *, pNewBackend->iNbUrls+1); // +1 for end NULL.
663 memcpy (pNewBackend->cUrlLabels, cUrlLabels, iNbUrls * sizeof (gchar*)); // we take N first labels given by the backend.
664 pNewBackend->cUrlLabels[iNbUrls] = D_("Tiny URL"); // + tiny-url.
665 pNewBackend->iPreferedUrlType = iPreferedUrlType;
666 pNewBackend->upload = pUploadFunc;
667 }
668