shortcut.h File Reference

#include <glib.h>
Include dependency graph for shortcut.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  shortcut_t

Defines

#define MAX_SHORTCUT_NESTING   5
#define shortcut_free(thiz)
 free the memory allocated to a shortcut_t structure and free the memory allocated to elements it contains and clear the pointer passed as argument

Enumerations

enum  shortcut_type_t {
  SHORTCUT_EMPTY = 0, SHORTCUT_TO_FILE, SHORTCUT_TO_WEB_LOCATION, SHORTCUT_TO_FOLDER,
  SHORTCUT_TO_APPLICATION, NUM_SHORTCUTS
}

Functions

int create_shortcut_file (const gchar *target_dir, const gchar *target_file, const gchar *target_display, const gchar *shortcut_dir, GString *shortcut_file)
 create a shortcut file
int parse_shortcut_file (const gchar *directory, const gchar *filename, shortcut_t **p_shortcut)
 get details from shortcut file parses shortcut files recursively when applicable
void shortcut_free_impl (shortcut_t *thiz)

Define Documentation

#define MAX_SHORTCUT_NESTING   5

File Name : shortcut.h

Description: Content browser functions handling shortcut files (xx.desktop) Copyright (C) 2008 iRex Technologies B.V. All rights reserved.

Definition at line 46 of file shortcut.h.

#define shortcut_free ( thiz   ) 
Value:
{                               \
            shortcut_free_impl(thiz);   \
            (thiz) = NULL;              \
        }

free the memory allocated to a shortcut_t structure and free the memory allocated to elements it contains and clear the pointer passed as argument

---------------------------------------------------------------------------

Name : shortcut_free

Parameters:
[in] directory - directory in which the shortcut file (xx.desktop) is located
[in] fileinfo - details of the shortcut file
Returns:
ER_OK or error code

--------------------------------------------------------------------------

Definition at line 174 of file shortcut.h.

Referenced by activate_shortcut(), check_shortcut(), get_thumbnail(), load_items_in_model(), and parse_shortcut_file().


Enumeration Type Documentation

Enumerator:
SHORTCUT_EMPTY 
SHORTCUT_TO_FILE 
SHORTCUT_TO_WEB_LOCATION 
SHORTCUT_TO_FOLDER 
SHORTCUT_TO_APPLICATION 
NUM_SHORTCUTS 

Definition at line 60 of file shortcut.h.


Function Documentation

int create_shortcut_file ( const gchar *  target_dir,
const gchar *  target_file,
const gchar *  target_display,
const gchar *  shortcut_dir,
GString *  shortcut_file 
)

create a shortcut file

---------------------------------------------------------------------------

Name : create_shortcut_file

Parameters:
[in] target_dir - folder in which the target is located specified as an absolute path
[in] target_file - file or folder to which the shortcut must point
[in] target_display - name displayed for target
[in] shortcut_dir - directory in which the shortcut file (xx.desktop) must be created specified as an absolute path
[out] shortcut_file - filename of the shortcut file created in shortcut_dir, or ignored when caller passes a NULL pointer here. Note: caller must allocate and release this GString.
Returns:
ER_OK - ok ER_NOT_FOUND - target not found ER_FORBIDDEN - directory or target directory not allowed or other error code

--------------------------------------------------------------------------

Definition at line 98 of file shortcut.c.

References ER_NOT_FOUND, ER_OK, ER_OPEN_ERROR, ER_WRITE_ERROR, FILE_EXT_SHORTCUT, FILE_EXT_SHORTCUT_TO_DIR, FILE_SHORTCUT, FOLDER_SHORTCUT, SHORTCUT_EMPTY, SHORTCUT_TO_FILE, and SHORTCUT_TO_FOLDER.

Referenced by create_shortcut_item().

00103 {
00104     int             ret = ER_OK;     // return code
00105 
00106     g_assert( target_dir            && *target_dir   == '/'    );
00107     g_assert( target_file           && *target_file            );
00108     g_assert( target_display        && *target_display         );
00109     g_assert( shortcut_dir          && *shortcut_dir == '/'    );
00110     g_assert( shortcut_file == NULL || shortcut_file->len == 0 );
00111     g_assert( strlen(target_dir) < 256);
00112     g_assert( strlen(target_file) < 256);
00113     g_assert( strlen(shortcut_dir) < 256);
00114 
00115     // determine shortcut type
00116     gchar *target_path = g_strdup_printf("%s/%s", target_dir, target_file);
00117 
00118     shortcut_type_t shortcut_type = SHORTCUT_EMPTY;
00119     const gchar *shortcut_ext = "";
00120     if ( g_file_test(target_path, G_FILE_TEST_IS_REGULAR) )
00121     {
00122         shortcut_type = SHORTCUT_TO_FILE;
00123         shortcut_ext  = FILE_EXT_SHORTCUT;
00124     }
00125     else if ( g_file_test(target_path, G_FILE_TEST_IS_DIR) )
00126     {
00127         shortcut_type = SHORTCUT_TO_FOLDER;
00128         shortcut_ext  = FILE_EXT_SHORTCUT_TO_DIR;
00129     }
00130     else
00131     {
00132         ret = ER_NOT_FOUND;
00133         goto out;
00134     }
00135 
00136     // determine shortcut filename
00137     int seq = 0;
00138     char file[256];
00139     char shortcut_fullname[512];
00140     while (1) {
00141         seq++;
00142         sprintf(file, "%s_%03d.%s", target_file, seq, shortcut_ext);
00143         sprintf(shortcut_fullname, "%s/%s", shortcut_dir, file);
00144         if (!g_file_test(shortcut_fullname, G_FILE_TEST_EXISTS)) break;
00145     }
00146 
00147     // determine relative path shortcut -> target
00148     // skip identical pre-fix
00149     gchar *cp1 = target_path;
00150     gchar *cp2 = shortcut_fullname;
00151     while ( *cp1 != '\0'  &&  *cp1 == *cp2 )
00152     {
00153         cp1++;
00154         cp2++;
00155     }
00156     while ( *(cp1 - 1) != '/' )
00157     {
00158         cp1--;
00159         cp2--;
00160     }
00161     // count parent directories to traverse
00162     gboolean done = FALSE;
00163     GString *shortcut_target = g_string_new("");
00164     while ( !done )
00165     {
00166         while ( *cp2 == '/' )
00167         {
00168             cp2++;
00169         }
00170         cp2 = strchr(cp2, '/');
00171         if (cp2)
00172         {
00173             g_string_append(shortcut_target, "../");
00174         }
00175         else
00176         {
00177             done = TRUE;
00178         }
00179     }
00180     // append remaining part of shortcut target
00181     g_string_append(shortcut_target, cp1);
00182 
00183     FILE *fp = fopen(shortcut_fullname, "w");
00184     if (fp == NULL)
00185     {
00186         ret = ER_OPEN_ERROR;
00187         goto out2;
00188     }
00189 
00190     int rc = 0;
00191     // write shortcut details
00192     switch (shortcut_type)
00193     {
00194         case SHORTCUT_TO_FILE:
00195         {
00196             gchar* temp_uri = g_uri_escape_string(shortcut_target->str, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
00197             rc = fprintf( fp,
00198                           FILE_SHORTCUT,
00199                           temp_uri,                 // URL=
00200                           target_display        );  // Name=
00201             g_free(temp_uri   );
00202             break;
00203         }
00204         case SHORTCUT_TO_FOLDER:
00205             rc = fprintf( fp,
00206                           FOLDER_SHORTCUT,
00207                           shortcut_target->str,     // Path=
00208                           target_display        );  // Name=
00209             break;
00210 
00211         default:
00212             g_assert_not_reached();
00213     }
00214     if (rc <= 0)
00215     {
00216         ret = ER_WRITE_ERROR;
00217     }
00218 
00219     rc = fclose(fp);
00220     if (rc != 0)
00221     {
00222         ret = ER_WRITE_ERROR;
00223     }
00224 
00225     // set output parameters
00226     if (ret == ER_OK && shortcut_file)
00227     {
00228         g_string_assign(shortcut_file, file);
00229     }
00230 
00231 out2:
00232     g_string_free(shortcut_target, TRUE);
00233 out:
00234     g_free(target_path);
00235     return ret;
00236 }

Here is the caller graph for this function:

int parse_shortcut_file ( const gchar *  directory,
const gchar *  filename,
shortcut_t **  p_shortcut 
)

get details from shortcut file parses shortcut files recursively when applicable

---------------------------------------------------------------------------

Name : parse_shortcut_file

Parameters:
[in] directory - directory in which the shortcut file (xx.desktop) is located
[in] filename - filename of the shortcut file
[out] p_shortcut - structure with details of the requested shortcut, caller must release this with shortcut_free()
Returns:
ER_OK - ok ER_NOT_FOUND - target location not found ER_INVALID_DATA - contents of shortcut file is corrupt ER_FORBIDDEN - target directory not allowed or other error code

--------------------------------------------------------------------------

Definition at line 239 of file shortcut.c.

References shortcut_t::application, shortcut_t::comment, cp, shortcut_t::details, ER_FAIL, ER_INVALID_DATA, ER_NOT_FOUND, ER_OK, ERRORPRINTF, shortcut_t::filepath, shortcut_t::folder, shortcut_t::keyfile, shortcut_t::name, parse_file_url(), parse_folder_path(), path, path_has_invalid_characters(), shortcut_free, shortcut_new(), SHORTCUT_TO_APPLICATION, SHORTCUT_TO_FILE, SHORTCUT_TO_FOLDER, SHORTCUT_TO_WEB_LOCATION, shortcut_t::type, and shortcut_t::web.

Referenced by activate_shortcut(), check_shortcut(), get_thumbnail(), and load_items_in_model().

00242 {
00243     g_assert(directory  && *directory );
00244     g_assert(filename   && *filename  );
00245     g_assert(p_shortcut && *p_shortcut == NULL);
00246 
00247     GKeyFile *keyfile = g_key_file_new();
00248     shortcut_t *shortcut = shortcut_new();
00249     shortcut->keyfile = keyfile;
00250     gchar *filepath = g_strdup_printf("%s/%s", directory, filename);
00251     shortcut->filepath = filepath;
00252 
00253     int ret = ER_OK;
00254     if (!g_file_test(filepath, G_FILE_TEST_IS_REGULAR))
00255     {
00256         ret = ER_NOT_FOUND;
00257         goto out;
00258     }
00259 
00260     if (!g_key_file_load_from_file( keyfile,
00261                                     filepath,
00262                                     G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
00263                                     NULL))
00264     {
00265         ret = ER_INVALID_DATA;
00266         goto out;
00267     }
00268 
00269     // get name
00270     shortcut->name = g_key_file_get_locale_string( keyfile,
00271                                           G_KEY_FILE_DESKTOP_GROUP,
00272                                           G_KEY_FILE_DESKTOP_KEY_NAME,
00273                                           NULL,
00274                                           NULL );
00275     if (shortcut->name == NULL)
00276     {
00277         ret = ER_INVALID_DATA;
00278         goto out;
00279     }
00280 
00281     // get comments
00282     shortcut->comment = g_key_file_get_locale_string( keyfile,
00283                                   G_KEY_FILE_DESKTOP_GROUP,
00284                                   G_KEY_FILE_DESKTOP_KEY_COMMENT,
00285                                   NULL,
00286                                   NULL );
00287 
00288     // get version (optional)
00289     gchar* version = g_key_file_get_string( keyfile,
00290                                    G_KEY_FILE_DESKTOP_GROUP,
00291                                    G_KEY_FILE_DESKTOP_KEY_VERSION,
00292                                    NULL );
00293     if (version != NULL)
00294     {
00295         int compare = strcmp(version, "1.0");
00296         g_free(version);
00297         if (compare != 0) {
00298             ret = ER_INVALID_DATA;
00299             goto out;
00300         }
00301     }
00302 
00303     // get type
00304     gchar *type = g_key_file_get_string( keyfile,
00305                                    G_KEY_FILE_DESKTOP_GROUP,
00306                                    G_KEY_FILE_DESKTOP_KEY_TYPE,
00307                                    NULL );
00308     if (type == NULL)
00309     {
00310         // type not found: error
00311         ret = ER_INVALID_DATA;
00312         goto out;
00313     }
00314 
00315     // type found: store in shortcut
00316     if ( strcmp(type, G_KEY_FILE_DESKTOP_TYPE_LINK) == 0 )
00317     {
00318         shortcut->type = SHORTCUT_TO_FILE;
00319     }
00320     else if ( strcmp(type, G_KEY_FILE_DESKTOP_TYPE_DIRECTORY) == 0 )
00321     {
00322         shortcut->type = SHORTCUT_TO_FOLDER;
00323     }
00324     else if ( strcmp(type, G_KEY_FILE_DESKTOP_TYPE_APPLICATION) == 0 )
00325     {
00326         shortcut->type = SHORTCUT_TO_APPLICATION;
00327     }
00328     else
00329     {
00330         g_free(type);
00331         ret = ER_INVALID_DATA;
00332         goto out;
00333     }
00334     g_free(type);
00335 
00336     // get type-dependent keys
00337     switch (shortcut->type)
00338     {
00339         case SHORTCUT_TO_FILE:
00340         {
00341             // get url
00342             gchar *url = g_key_file_get_string( keyfile,
00343                                            G_KEY_FILE_DESKTOP_GROUP,
00344                                            G_KEY_FILE_DESKTOP_KEY_URL,
00345                                            NULL );
00346             if (url == NULL)
00347             {
00348                 ret = ER_INVALID_DATA;
00349                 goto out;
00350             }
00351 
00352             // url found: convert to path, store in shortcut
00353 
00354             // get scheme from url
00355             // note: scheme might indicate url points to a web location
00356             if ( g_str_has_prefix(url, "http:") || g_str_has_prefix(url, "https:") )
00357             {
00358                 // web location: remember details and leave
00359                 shortcut->type = SHORTCUT_TO_WEB_LOCATION;
00360                 shortcut->details.web.url = url;
00361                 ret = ER_OK;
00362                 break;  // exit switch
00363             }
00364             else if ( g_str_has_prefix(url, "file:") )
00365             {
00366                 // local file location: get real path
00367                 ret = parse_file_url( directory, url, shortcut );
00368             }
00369             else
00370             {
00371                 // scheme not implemented
00372                 ret = ER_INVALID_DATA;
00373                 goto out;
00374             }
00375 
00376             // clean up
00377             g_free(url);
00378             break;
00379         }
00380         case SHORTCUT_TO_FOLDER:
00381         {
00382             // get path
00383             gchar *path = g_key_file_get_string( keyfile,
00384                                            G_KEY_FILE_DESKTOP_GROUP,
00385                                            G_KEY_FILE_DESKTOP_KEY_PATH,
00386                                            NULL );
00387             if (path == NULL)
00388             {
00389                 ret = ER_INVALID_DATA;
00390                 goto out;
00391             }
00392 
00393             // key found: check on invalid characters
00394             if ( path_has_invalid_characters(path) )
00395             {
00396                 ret = ER_INVALID_DATA;
00397                 goto out;
00398             }
00399 
00400             // path found: convert to realpath, store in shortcut
00401             ret = parse_folder_path( directory, path, shortcut );
00402             shortcut->details.folder.path = path;
00403             break;
00404         }
00405         // note: no nesting of shortcut to application
00406         case SHORTCUT_TO_APPLICATION:
00407         {
00408             // get exec
00409             gchar *executable = g_key_file_get_string( keyfile,
00410                                            G_KEY_FILE_DESKTOP_GROUP,
00411                                            G_KEY_FILE_DESKTOP_KEY_EXEC,
00412                                            NULL );
00413             if (executable == NULL)
00414             {
00415                 ret = ER_INVALID_DATA;
00416                 goto out;
00417             }
00418 
00419             // key found: store in shortcut
00420             if (strncmp(executable, "./",  2) == 0 || strncmp(executable, "../", 3) == 0)
00421             {
00422                 // relative path: prepend shortcut directory
00423                 // shell quote to preserve spaces in directory
00424                 gchar *directory_quoted = g_shell_quote(directory);
00425                 gchar *cp = g_strdup_printf("%s/%s", directory_quoted, executable);
00426                 g_free(directory_quoted);
00427                 g_free(executable);
00428                 executable = cp;
00429             }
00430             shortcut->details.application.command_line = executable;
00431 
00432             // get path (optional)
00433             gchar* path = g_key_file_get_string( keyfile,
00434                                            G_KEY_FILE_DESKTOP_GROUP,
00435                                            G_KEY_FILE_DESKTOP_KEY_PATH,
00436                                            NULL );
00437             if (path != NULL)
00438             { 
00439                 // key found: check on invalid characters
00440                 if ( path_has_invalid_characters(path) )
00441                 {
00442                     g_free(path);
00443                     ret = ER_INVALID_DATA;
00444                     goto out;
00445                 }
00446                 // path ok: store in shortcut
00447                 shortcut->details.application.work_dir = path;
00448             }
00449             break;
00450         }
00451         default:
00452             ERRORPRINTF("unknown type %d", shortcut->type);
00453             ret = ER_FAIL;
00454             break;
00455     }
00456 
00457     if (ret == ER_OK)
00458     {
00459         *p_shortcut = shortcut;
00460         return ER_OK;
00461     }
00462 
00463 out:
00464     shortcut_free(shortcut);
00465     return ret;
00466 }

Here is the call graph for this function:

Here is the caller graph for this function:

void shortcut_free_impl ( shortcut_t thiz  ) 

Definition at line 637 of file shortcut.c.

References shortcut_t::application, shortcut_t::comment, shortcut_t::details, ERRORPRINTF, shortcut_t::file, shortcut_t::filepath, shortcut_t::folder, shortcut_t::keyfile, shortcut_t::name, SHORTCUT_EMPTY, SHORTCUT_TO_APPLICATION, SHORTCUT_TO_FILE, SHORTCUT_TO_FOLDER, SHORTCUT_TO_WEB_LOCATION, shortcut_t::type, and shortcut_t::web.

00638 {
00639     if (thiz == NULL) return;
00640 
00641     g_free(thiz->filepath);
00642     if (thiz->keyfile)
00643     {
00644         g_key_file_free(thiz->keyfile);
00645     }
00646     g_free(thiz->name);
00647     g_free(thiz->comment);
00648     switch (thiz->type)
00649     {
00650         case SHORTCUT_EMPTY:
00651             ; //ignore
00652             break;
00653 
00654         case SHORTCUT_TO_FILE:
00655             g_free(thiz->details.file.directory);
00656             g_free(thiz->details.file.filename );
00657             break;
00658 
00659         case SHORTCUT_TO_WEB_LOCATION:
00660             g_free(thiz->details.web.url);
00661             break;
00662 
00663         case SHORTCUT_TO_FOLDER:
00664             g_free(thiz->details.folder.path);
00665             g_free(thiz->details.folder.directory);
00666             g_free(thiz->details.folder.filename );
00667             break;
00668 
00669         case SHORTCUT_TO_APPLICATION:
00670             g_free(thiz->details.application.command_line);
00671             break;
00672 
00673         default:
00674             ERRORPRINTF("illegal shortcut type [%d]", thiz->type);
00675             ; //ignore
00676     }
00677 
00678     g_free(thiz);
00679 }

Generated by  doxygen 1.6.2-20100208