1 /*
2  *  Copyright (C) 2005 Marc Pavot <marc.pavot@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  */
19 
20 #include "ario-util.h"
21 #include <glib.h>
22 #include <glib/gstdio.h>
23 #include <gtk/gtk.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <curl/curl.h>
29 #include <glib/gi18n.h>
30 #ifdef WIN32
31 #include <windows.h>
32 #endif
33 
34 #include "ario-debug.h"
35 #include "covers/ario-cover.h"
36 #include "lib/ario-conf.h"
37 #include "preferences/ario-preferences.h"
38 
39 /* Maximum number of covers to put in drag and drop icon */
40 #define MAX_COVERS_IN_DRAG 3
41 
42 char *
ario_util_format_time(const int time)43 ario_util_format_time (const int time)
44 {
45         ARIO_LOG_FUNCTION_START;
46         int sec, min, hours;
47 
48         if (time < 0)
49                 return g_strdup_printf (_("n/a"));
50 
51         hours = (int)(time / 3600);
52         min = (int)((time % 3600) / 60) ;
53         sec = (time % 60);
54 
55         if (hours > 0)
56                 return g_strdup_printf ("%d:%02i:%02i", hours, min, sec);
57         else
58                 return g_strdup_printf ("%02i:%02i", min, sec);
59 }
60 
61 void
ario_util_format_time_buf(const int time,char * buf,int buf_len)62 ario_util_format_time_buf (const int time,
63                            char *buf,
64                            int buf_len)
65 {
66         ARIO_LOG_FUNCTION_START;
67         int sec, min, hours;
68 
69         if (time < 0)
70                 g_snprintf (buf, buf_len, _("n/a"));
71 
72         hours = (int)(time / 3600);
73         min = (int)((time % 3600) / 60) ;
74         sec = (time % 60);
75 
76         if (hours > 0)
77                 g_snprintf (buf, buf_len, "%d:%02i:%02i", hours, min, sec);
78         else
79                 g_snprintf (buf, buf_len, "%02i:%02i", min, sec);
80 }
81 
82 char *
ario_util_format_total_time(const int time)83 ario_util_format_total_time (const int time)
84 {
85         ARIO_LOG_FUNCTION_START;
86         gchar *res;
87         gchar *tmp;
88         int temp_time;
89         int sec, min, hours, days;
90 
91         if (time < 0)
92                 return g_strdup_printf (_("n/a"));
93 
94         /* Compute number of days */
95         days = (int)(time / 86400);
96         temp_time = (time % 86400);
97 
98         /* Compute number of hours */
99         hours = (int)(temp_time / 3600);
100         temp_time = (temp_time % 3600);
101 
102         /* Compute number of minutes */
103         min = (int)(temp_time / 60);
104 
105         /* Compute number of seconds */
106         sec = (temp_time % 60);
107 
108         /* Format result string */
109         res = g_strdup_printf ("%d %s", sec, _("seconds"));
110         if (min != 0) {
111                 tmp = g_strdup_printf ("%d %s, %s", min, _("minutes"), res);
112                 g_free (res);
113                 res = tmp;
114         }
115 
116         if (hours != 0) {
117                 tmp = g_strdup_printf ("%d %s, %s", hours, _("hours"), res);
118                 g_free (res);
119                 res = tmp;
120         }
121 
122         if (days != 0) {
123                 tmp = g_strdup_printf ("%d %s, %s", days, _("days"), res);
124                 g_free (res);
125                 res = tmp;
126         }
127 
128         return res;
129 }
130 
131 void
ario_util_format_track_buf(const gchar * track,char * buf,int buf_len)132 ario_util_format_track_buf (const gchar *track,
133                             char *buf,
134                             int buf_len)
135 {
136         ARIO_LOG_FUNCTION_START;
137         gchar *slash;
138         gchar tmp[INTLEN];
139 
140         if (!track) {
141                 *buf = '\0';
142                 return;
143         }
144 
145         /* Some tracks are x/y, we only want to display x */
146         slash = g_strrstr (track, "/");
147         if (slash) {
148                 g_snprintf (tmp, ario_util_min (INTLEN, slash - track + 1), "%s", track);
149                 g_snprintf (buf, buf_len, "%02i", atoi (tmp));
150         } else {
151                 g_snprintf (buf, buf_len, "%02i", atoi (track));
152         }
153 }
154 
155 gchar *
ario_util_format_title(ArioServerSong * server_song)156 ario_util_format_title (ArioServerSong *server_song)
157 {
158         ARIO_LOG_FUNCTION_START;
159         gchar *dot;
160         gchar *slash;
161         gchar *res = NULL;
162 
163         if (!server_song) {
164                 res = ARIO_SERVER_UNKNOWN;
165         } else if (server_song->title) {
166                 res = server_song->title;
167         } else if (server_song->name) {
168                 res = server_song->name;
169         } else {
170                 /* Original format is : "path/to/filename.extension" or http://path/to/address:port
171                  * or lastfm://path/to/address
172                  * We only want to display filename or http/last.fm address */
173                 if (!g_ascii_strncasecmp (server_song->file, "http://", 7)
174                     || !g_ascii_strncasecmp (server_song->file, "lastfm://", 7)) {
175                         res = server_song->file;
176                 } else {
177                         slash = g_strrstr (server_song->file, "/");
178                         if (slash) {
179                                 dot = g_strrstr (slash + 1, ".");
180                                 if (dot)
181                                         server_song->title = g_strndup (slash+1, dot - slash - 1);
182                                 else
183                                         server_song->title = g_strdup (slash+1);
184                                 res = server_song->title;
185                         } else {
186                                 res = server_song->file;
187                         }
188                 }
189         }
190         return res;
191 }
192 
193 void
ario_util_init_icons(void)194 ario_util_init_icons (void)
195 {
196         ARIO_LOG_FUNCTION_START;
197 
198         GtkIconTheme *icon_theme;
199         icon_theme = gtk_icon_theme_get_default ();
200         gtk_icon_theme_append_search_path (icon_theme, PIXMAP_PATH);
201 }
202 
203 const char *
ario_util_config_dir(void)204 ario_util_config_dir (void)
205 {
206         ARIO_LOG_FUNCTION_START;
207         static char *config_dir = NULL;
208 
209         if (!config_dir) {
210                 config_dir = g_build_filename (g_get_user_config_dir (),
211                                                "ario",
212                                                NULL);
213                 if (!ario_file_test (config_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
214                         ario_util_mkdir (config_dir);
215         }
216 
217         return config_dir;
218 }
219 
220 gboolean
ario_util_uri_exists(const char * uri)221 ario_util_uri_exists (const char *uri)
222 {
223         g_return_val_if_fail (uri != NULL, FALSE);
224 
225         return ario_file_test (uri, G_FILE_TEST_EXISTS);
226 }
227 
228 
229 void
ario_util_unlink_uri(const char * uri)230 ario_util_unlink_uri (const char *uri)
231 {
232         ARIO_LOG_FUNCTION_START;
233         gchar *uri_fse = g_filename_from_utf8 (uri, -1, NULL, NULL, NULL);
234         if (!uri_fse)
235                 return;
236 
237         g_unlink (uri_fse);
238 
239         g_free (uri_fse);
240 }
241 
242 void
ario_util_mkdir(const char * uri)243 ario_util_mkdir (const char *uri)
244 {
245         ARIO_LOG_FUNCTION_START;
246         gchar *uri_fse = g_filename_from_utf8 (uri, -1, NULL, NULL, NULL);
247         if (!uri_fse)
248                 return;
249 
250         g_mkdir_with_parents (uri_fse, 0750);
251 
252         g_free (uri_fse);
253 }
254 
255 void
ario_util_copy_file(const char * src_uri,const char * dest_uri)256 ario_util_copy_file (const char *src_uri,
257                      const char *dest_uri)
258 {
259         ARIO_LOG_FUNCTION_START;
260         gchar *contents;
261         gsize length;
262 
263         /* Get file content */
264         if (! ario_file_get_contents (src_uri,
265                                       &contents,
266                                       &length,
267                                       NULL)) {
268                 return;
269         }
270 
271         /* Write file content */
272         ario_file_set_contents (dest_uri,
273                                 contents,
274                                 length,
275                                 NULL);
276         g_free (contents);
277 }
278 
279 typedef struct _download_struct{
280         char *data;
281         int size;
282 } download_struct;
283 
284 /* Limit downloaded file to 5MB */
285 #define MAX_SIZE 5*1024*1024
286 
287 static size_t
ario_util_write_data(void * buffer,size_t size,size_t nmemb,download_struct * download_data)288 ario_util_write_data(void *buffer,
289                      size_t size,
290                      size_t nmemb,
291                      download_struct *download_data)
292 {
293         ARIO_LOG_FUNCTION_START;
294 
295         if (!size || !nmemb)
296                 return 0;
297 
298         if (download_data->data == NULL)
299                 download_data->size = 0;
300 
301         /* Increase buffer size if needed */
302         download_data->data = g_realloc (download_data->data,
303                                          (gulong)(size*nmemb+download_data->size) + 1);
304 
305         /* Append received data to buffer */
306         memset (&(download_data->data)[download_data->size], '\0', (size*nmemb)+1);
307         memcpy (&(download_data->data)[download_data->size], buffer, size*nmemb);
308 
309         /* Increase size */
310         download_data->size += size*nmemb;
311         if (download_data->size >= MAX_SIZE)
312                 return 0;
313 
314         return size*nmemb;
315 }
316 
317 void
ario_util_download_file(const char * uri,const char * post_data,const int post_size,const struct curl_slist * headers,int * size,char ** data)318 ario_util_download_file (const char *uri,
319                          const char *post_data,
320                          const int post_size,
321                          const struct curl_slist *headers,
322                          int* size,
323                          char** data)
324 {
325         ARIO_LOG_FUNCTION_START;
326         ARIO_LOG_DBG ("Download:%s", uri);
327         download_struct download_data;
328         const gchar* address;
329         int port;
330 
331         /* Initialize curl */
332         CURL* curl = curl_easy_init ();
333         if (!curl)
334                 return;
335 
336         *size = 0;
337         *data = NULL;
338 
339         download_data.size = 0;
340         download_data.data = NULL;
341 
342         /* set uri */
343         curl_easy_setopt (curl, CURLOPT_URL, uri);
344         /* set callback data */
345         curl_easy_setopt (curl, CURLOPT_WRITEDATA, &download_data);
346         /* set callback function */
347         curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)ario_util_write_data);
348         /* set timeout */
349         curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 20);
350         /* set redirect */
351         curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION ,1);
352         /* set NO SIGNAL */
353         curl_easy_setopt (curl, CURLOPT_NOSIGNAL, TRUE);
354 
355         /* Use a proxy if one is configured */
356         if (ario_conf_get_boolean (PREF_USE_PROXY, PREF_USE_PROXY_DEFAULT)) {
357                 address = ario_conf_get_string (PREF_PROXY_ADDRESS, PREF_PROXY_ADDRESS_DEFAULT);
358                 port =  ario_conf_get_integer (PREF_PROXY_PORT, PREF_PROXY_PORT_DEFAULT);
359                 if (address) {
360                         curl_easy_setopt (curl, CURLOPT_PROXY, address);
361                         curl_easy_setopt (curl, CURLOPT_PROXYPORT, port);
362                 } else {
363                         ARIO_LOG_DBG ("Proxy enabled, but no proxy defined");
364                 }
365         }
366 
367         /* Handles data for POST requests */
368         if (post_data) {
369                 curl_easy_setopt (curl, CURLOPT_POST, TRUE);
370                 curl_easy_setopt (curl, CURLOPT_POSTFIELDS, post_data);
371                 curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, post_size);
372         }
373 
374         if (headers) {
375                 curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers);
376         }
377 
378         /* Performs the request */
379         curl_easy_perform (curl);
380 
381         *size = download_data.size;
382         *data = download_data.data;
383 
384         curl_easy_cleanup (curl);
385 }
386 
387 void
ario_util_string_replace(char ** string,const char * old,const char * new)388 ario_util_string_replace (char **string,
389                           const char *old,
390                           const char *new)
391 {
392         ARIO_LOG_FUNCTION_START;
393         gchar **strsplit;
394         GString *str;
395         int i;
396 
397         /* Check if old is present in string */
398         if (!g_strstr_len (*string, -1, old))
399                 return;
400 
401         /* Split string around 'old' */
402         strsplit = g_strsplit (*string, old, 0);
403 
404         if (!strsplit)
405                 return;
406 
407         if (!strsplit[0]) {
408                 g_strfreev (strsplit);
409                 return;
410         }
411 
412         /* Create a new string */
413         str = g_string_new (strsplit[0]);
414 
415         /* Append splited parts to the new string */
416         for (i = 1; strsplit[i] && g_utf8_collate (strsplit[i], ""); ++i) {
417                 g_string_append (str, new);
418                 g_string_append (str, strsplit[i]);
419         }
420         g_strfreev (strsplit);
421 
422         g_free (*string);
423         *string = str->str;
424         g_string_free (str, FALSE);
425 }
426 
427 void
ario_util_load_uri(const char * uri)428 ario_util_load_uri (const char *uri)
429 {
430         ARIO_LOG_FUNCTION_START;
431 #ifdef WIN32
432         ShellExecute (GetDesktopWindow(), "open", uri, NULL, NULL, SW_SHOW);
433 #else
434         gchar *command = g_strdup_printf ("xdg-open %s", uri);
435         g_spawn_command_line_async (command, NULL);
436         g_free (command);
437 #endif
438 }
439 
440 char *
ario_util_format_keyword(const char * keyword)441 ario_util_format_keyword (const char *keyword)
442 {
443         ARIO_LOG_FUNCTION_START;
444         gchar *tmp;
445         int i, j;
446         int length;
447         gchar *ret;
448 
449         /* List of modifications done on the keuword used for the search */
450         const gchar *to_remove[] = {"cd 1", "cd 2", "cd 3", "cd 4", "cd 5",
451                 "cd1", "cd2", "cd3", "cd4", "cd5",
452                 "disc", "disk", "disque", "remastered", NULL};
453 
454         /* Normalize keyword */
455         ret = g_utf8_normalize (keyword, -1, G_NORMALIZE_ALL);
456 
457         /* Converts all upper case ASCII letters to lower case ASCII letters */
458         tmp = g_ascii_strdown (ret, -1);
459         g_free (ret);
460         ret = tmp;
461 
462         /* We remove some useless words to make more accurate requests */
463         for (i = 0; to_remove[i]; ++i) {
464                 ario_util_string_replace (&ret, to_remove[i], " ");
465         }
466 
467         /* We escape the special characters */
468         length = g_utf8_strlen (ret, -1);
469         tmp = (char *) g_malloc0 (length);
470 
471         j = 0;
472         for (i = 0; ret[i]; ++i) {
473                 if (g_unichar_isalnum (ret[i]) ||
474                     (g_unichar_isspace (ret[i]) &&  j > 0 && !g_unichar_isspace (tmp[j-1]))) {
475                         tmp[j] = ret[i];
476                         ++j;
477                 }
478         }
479         tmp = g_realloc (tmp, j+1);
480         tmp[j] = '\0';
481 
482         g_free (ret);
483         ret = tmp;
484 
485         /* We escape spaces */
486         ario_util_string_replace (&ret, " ", "%20");
487 
488         return ret;
489 }
490 
491 char *
ario_util_format_keyword_for_lastfm(const char * keyword)492 ario_util_format_keyword_for_lastfm (const char *keyword)
493 {
494         ARIO_LOG_FUNCTION_START;
495 
496         /* Escape string */
497         return g_uri_escape_string (keyword, NULL, FALSE);
498 }
499 
500 #define DRAG_SIZE 70
501 #define DRAG_COVER_STEP 0.15
502 
503 static GdkPixbuf *
ario_util_get_dnd_pixbuf_from_cover_paths(GSList * covers)504 ario_util_get_dnd_pixbuf_from_cover_paths (GSList *covers)
505 {
506         ARIO_LOG_FUNCTION_START;
507         GSList *tmp;
508         int len = g_slist_length (covers);
509         GdkPixbuf *pixbuf, *cover;
510         int i = 0;
511         gdouble scale;
512 
513         if (len == 0) {
514                 /* No cover means no icon */
515                 pixbuf = NULL;
516         } else if (len == 1) {
517                 /* Only one cover, the icon is made of this cover */
518                 pixbuf = gdk_pixbuf_new_from_file_at_size (covers->data, DRAG_SIZE, DRAG_SIZE, NULL);
519         } else {
520                 /* Several covers */
521 
522                 /* Compute scale */
523                 scale = (1 - DRAG_COVER_STEP*(len-1));
524 
525                 /* Create empyt pixbuf */
526                 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, DRAG_SIZE, DRAG_SIZE);
527                 gdk_pixbuf_fill (pixbuf, 0);
528 
529                 for (tmp = covers; tmp; tmp = g_slist_next (tmp)) {
530                         /* Integrate cover in pixbuf */
531                         cover = gdk_pixbuf_new_from_file_at_size (tmp->data, (int) (scale*DRAG_SIZE), (int) (scale*DRAG_SIZE), NULL);
532                         if (!cover)
533                                 continue;
534 
535                         gdk_pixbuf_composite (cover, pixbuf,
536                                               (int) (i*DRAG_COVER_STEP*DRAG_SIZE), (int) (i*DRAG_COVER_STEP*DRAG_SIZE),
537                                               (int) (scale*DRAG_SIZE), (int) (scale*DRAG_SIZE),
538                                               (int) (i*DRAG_COVER_STEP*DRAG_SIZE), (int) (i*DRAG_COVER_STEP*DRAG_SIZE),
539                                               1.0, 1.0,
540                                               GDK_INTERP_HYPER,
541                                               255);
542                         g_object_unref (cover);
543                         ++i;
544                 }
545         }
546 
547         return pixbuf;
548 }
549 
550 GdkPixbuf *
ario_util_get_dnd_pixbuf_from_albums(const GSList * albums)551 ario_util_get_dnd_pixbuf_from_albums (const GSList *albums)
552 {
553         ARIO_LOG_FUNCTION_START;
554         const GSList *tmp;
555         GSList *covers = NULL;
556         gchar *cover_path;
557         ArioServerAlbum *ario_server_album;
558         int len = 0;
559         GdkPixbuf *pixbuf;
560 
561         if (!albums)
562                 return NULL;
563 
564         /* Get cover of each album */
565         for (tmp = albums; tmp && len < MAX_COVERS_IN_DRAG; tmp = g_slist_next (tmp)) {
566                 ario_server_album = tmp->data;
567 
568                 cover_path = ario_cover_make_cover_path (ario_server_album->artist, ario_server_album->album, SMALL_COVER);
569                 if (ario_util_uri_exists (cover_path)) {
570                         covers = g_slist_append (covers, cover_path);
571                         ++len;
572                 } else {
573                         g_free (cover_path);
574                 }
575         }
576 
577         /* Get the icon from covers */
578         pixbuf = ario_util_get_dnd_pixbuf_from_cover_paths (covers);
579 
580         g_slist_foreach (covers, (GFunc) g_free, NULL);
581         g_slist_free (covers);
582 
583         return pixbuf;
584 }
585 
586 GdkPixbuf *
ario_util_get_dnd_pixbuf(const GSList * criterias)587 ario_util_get_dnd_pixbuf (const GSList *criterias)
588 {
589         ARIO_LOG_FUNCTION_START;
590         const GSList *tmp;
591         ArioServerAlbum *server_album;
592         int len = 0;
593         ArioServerCriteria *criteria;
594         GSList *albums, *album_tmp;
595         GdkPixbuf *pixbuf;
596         gchar *cover_path;
597         GSList *covers = NULL;
598 
599         if (!criterias)
600                 return NULL;
601 
602         /* Get covers from criterias */
603         for (tmp = criterias; tmp && len < MAX_COVERS_IN_DRAG; tmp = g_slist_next (tmp)) {
604                 criteria = tmp->data;
605 
606                 /* Get albums from criteria */
607                 albums = ario_server_get_albums (criteria);
608 
609                 /* Get covers of albums */
610                 for (album_tmp = albums; album_tmp && len < MAX_COVERS_IN_DRAG; album_tmp = g_slist_next (album_tmp)) {
611                         server_album = album_tmp->data;
612                         cover_path = ario_cover_make_cover_path (server_album->artist, server_album->album, SMALL_COVER);
613                         if (ario_util_uri_exists (cover_path)) {
614                                 covers = g_slist_append (covers, cover_path);
615                                 ++len;
616                         } else {
617                                 g_free (cover_path);
618                         }
619                 }
620                 g_slist_foreach (albums, (GFunc) ario_server_free_album, NULL);
621                 g_slist_free (albums);
622         }
623 
624         /* Get the icon from covers */
625         pixbuf = ario_util_get_dnd_pixbuf_from_cover_paths (covers);
626 
627         g_slist_foreach (covers, (GFunc) g_free, NULL);
628         g_slist_free (covers);
629 
630         return pixbuf;
631 }
632 
633 gchar *
ario_util_convert_from_iso8859(const char * string)634 ario_util_convert_from_iso8859 (const char *string)
635 {
636         ARIO_LOG_FUNCTION_START;
637         char *ret, *tmp;
638 
639         tmp = g_convert (string, -1, (const gchar *) "ISO-8859-1", "UTF8", NULL, NULL, NULL);
640         ret = g_locale_from_utf8 (tmp, -1, NULL, NULL, NULL);
641         g_free (tmp);
642 
643         return ret;
644 }
645 
646 void
ario_util_sanitize_filename(char * filename)647 ario_util_sanitize_filename (char *filename)
648 {
649         ARIO_LOG_FUNCTION_START;
650         const char *to_strip = "#/*\"\\[]:;|=";
651         static unsigned char translate[256];
652         static gboolean initialized = FALSE;
653         int c;
654         unsigned char *tmp;
655 
656         if (!initialized) {
657                 for (c = 0; c < 256; c++)
658                         translate[c] = strchr (to_strip, c)?
659                                                ' ': (unsigned char) c;
660                 initialized = TRUE;
661         }
662 
663         /* We replace some special characters with spaces. */
664         for (tmp = (unsigned char *) filename; *tmp != '\0'; ++tmp)
665                 *tmp = translate[*tmp];
666 }
667 
668 gboolean
ario_file_get_contents(const gchar * filename,gchar ** contents,gsize * length,GError ** error)669 ario_file_get_contents (const gchar *filename, gchar **contents,
670                         gsize *length, GError **error)
671 {
672         ARIO_LOG_FUNCTION_START;
673         gboolean ret;
674         gchar *filename_fse;
675 
676         /* Convert filename to locale */
677         filename_fse = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
678         if (!filename_fse) {
679                 if (error)
680                         *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_NOENT,
681                                               "File `%s' not found", filename);
682                 return FALSE;
683         }
684 
685         /* Get file content */
686         ret = g_file_get_contents (filename_fse, contents, length, error);
687 
688         g_free (filename_fse);
689 
690         return ret;
691 }
692 
693 gboolean
ario_file_set_contents(const gchar * filename,const gchar * contents,gsize length,GError ** error)694 ario_file_set_contents (const gchar *filename, const gchar *contents,
695                         gsize length, GError **error)
696 {
697         ARIO_LOG_FUNCTION_START;
698         gboolean ret;
699         gchar *filename_fse;
700 
701         /* Convert filename to locale */
702         filename_fse = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
703         if (!filename_fse) {
704                 if (error)
705                         *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED,
706                                               "Could not write to file `%s'", filename);
707                 return FALSE;
708         }
709 
710         /* Set file content */
711         ret = g_file_set_contents (filename_fse, contents, length, error);
712 
713         g_free (filename_fse);
714 
715         return ret;
716 }
717 
718 gboolean
ario_file_test(const gchar * filename,GFileTest test)719 ario_file_test (const gchar *filename, GFileTest test)
720 {
721         ARIO_LOG_FUNCTION_START;
722         gboolean ret;
723         gchar *filename_fse;
724 
725         /* Convert filename to locale */
726         filename_fse = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
727         if (!filename_fse)
728                 return FALSE;
729 
730         /* Test file */
731         ret = g_file_test (filename_fse, test);
732 
733         g_free (filename_fse);
734 
735         return ret;
736 }
737 
738 const char *
ario_util_stristr(const char * haystack,const char * needle)739 ario_util_stristr (const char *haystack,
740                    const char *needle)
741 {
742         ARIO_LOG_FUNCTION_START;
743 
744         if (!needle || !*needle)
745                 return haystack;
746 
747         for (; *haystack; ++haystack) {
748                 if (toupper(*haystack) == toupper(*needle)) {
749                         /*
750                          * Matched starting char -- loop through remaining chars.
751                          */
752                         const char *h, *n;
753 
754                         for (h = haystack, n = needle; *h && *n; ++h, ++n) {
755                                 if (toupper(*h) != toupper(*n)) {
756                                         break;
757                                 }
758                         }
759                         /* matched all of 'needle' to null termination */
760                         if (!*n) {
761                                 /* return the start of the match */
762                                 return haystack;
763                         }
764                 }
765         }
766         return 0;
767 }
768 
769 GSList *
ario_util_gslist_randomize(GSList ** list,const int max)770 ario_util_gslist_randomize (GSList **list,
771                             const int max)
772 {
773         ARIO_LOG_FUNCTION_START;
774         GSList *ret = NULL, *tmp;
775         int i = 0;
776         int len = g_slist_length (*list);
777 
778         for (i = 0; i < max; ++i) {
779                 if (len <= 0)
780                         break;
781 
782                 /* Get a random element in list */
783                 tmp = g_slist_nth (*list, rand()%len);
784 
785                 /* Remove the element from list */
786                 *list = g_slist_remove_link (*list, tmp);
787 
788                 /* Append the element to the new list */
789                 ret = g_slist_concat (ret, tmp);
790                 len--;
791         }
792 
793         return ret;
794 }
795 
796 gchar *
ario_util_format_for_http(const gchar * text)797 ario_util_format_for_http (const gchar *text)
798 {
799         int i;
800         int length;
801         gchar *res;
802 
803         /* Normalize */
804         res = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
805 
806         /* We escape special characters */
807         length = g_utf8_strlen (res, -1);
808         for(i = 0; i < length; ++i)
809         {
810                 if (!g_unichar_isalnum (res[i])) {
811                         res[i]=' ';
812                 }
813         }
814 
815         /* We escape spaces */
816         ario_util_string_replace (&res, " ", "%20");
817 
818         return res;
819 }
820 
821