From f5691c7ea5e4e5325d311f72b8e9505a08e3ab8c Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Mon, 26 Nov 2007 15:10:15 -0800 Subject: [PATCH] shell32: add xdg-user-dirs lookup code --- dlls/shell32/Makefile.in | 3 dlls/shell32/xdg-user-dir-lookup.c | 220 ++++++++++++++++++++++++++++++++++++ dlls/shell32/xdg-user-dir-lookup.h | 22 ++++ 3 files changed, 244 insertions(+), 1 deletions(-) diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in index 0da3e95..a555af9 100644 --- a/dlls/shell32/Makefile.in +++ b/dlls/shell32/Makefile.in @@ -50,7 +50,8 @@ C_SRCS = \ shv_item_cmenu.c \ systray.c \ trash.c \ - xdg.c + xdg.c \ + xdg-user-dir-lookup.c RC_SRCS = shres.rc diff --git a/dlls/shell32/xdg-user-dir-lookup.c b/dlls/shell32/xdg-user-dir-lookup.c new file mode 100644 index 0000000..79b6967 --- /dev/null +++ b/dlls/shell32/xdg-user-dir-lookup.c @@ -0,0 +1,220 @@ +/* + * From: http://www.freedesktop.org/wiki/Software/xdg-user-dirs + * + * Copyright (c) 2007 Red Hat, inc + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include + +#include "wine/debug.h" +#include "winbase.h" + +/** + * xdg_user_dir_lookup_with_fallback: + * @type: a string specifying the type of directory + * @fallback: value to use if the directory isn't specified by the user + * @returns: a newly allocated absolute pathname + * + * Looks up a XDG user directory of the specified type. + * Example of types are "DESKTOP" and "DOWNLOAD". + * + * In case the user hasn't specified any directory for the specified + * type the value returned is @fallback. + * + * The return value is newly allocated and must be freed. + * The return value is never NULL if @fallback != NULL, unless + * out of memory. + **/ +static char * +xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback) +{ + FILE *file; + char *home_dir, *config_home, *config_file; + char buffer[512]; + char *user_dir; + char *p, *d; + int len; + int relative; + + home_dir = getenv ("HOME"); + + if (home_dir == NULL) + goto error; + + config_home = getenv ("XDG_CONFIG_HOME"); + if (config_home == NULL || config_home[0] == 0) + { + config_file = (char*) HeapAlloc (GetProcessHeap(), 0, strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1); + if (config_file == NULL) + goto error; + + strcpy (config_file, home_dir); + strcat (config_file, "/.config/user-dirs.dirs"); + } + else + { + config_file = (char*) HeapAlloc (GetProcessHeap(), 0, strlen (config_home) + strlen ("/user-dirs.dirs") + 1); + if (config_file == NULL) + goto error; + + strcpy (config_file, config_home); + strcat (config_file, "/user-dirs.dirs"); + } + + file = fopen (config_file, "r"); + HeapFree (GetProcessHeap(), 0, config_file); + if (file == NULL) + goto error; + + user_dir = NULL; + while (fgets (buffer, sizeof (buffer), file)) + { + /* Remove newline at end */ + len = strlen (buffer); + if (len > 0 && buffer[len-1] == '\n') + buffer[len-1] = 0; + + p = buffer; + while (*p == ' ' || *p == '\t') + p++; + + if (strncmp (p, "XDG_", 4) != 0) + continue; + p += 4; + if (strncmp (p, type, strlen (type)) != 0) + continue; + p += strlen (type); + if (strncmp (p, "_DIR", 4) != 0) + continue; + p += 4; + + while (*p == ' ' || *p == '\t') + p++; + + if (*p != '=') + continue; + p++; + + while (*p == ' ' || *p == '\t') + p++; + + if (*p != '"') + continue; + p++; + + relative = 0; + if (strncmp (p, "$HOME/", 6) == 0) + { + p += 6; + relative = 1; + } + else if (*p != '/') + continue; + + if (relative) + { + user_dir = (char*) HeapAlloc (GetProcessHeap(), 0, strlen (home_dir) + 1 + strlen (p) + 1); + if (user_dir == NULL) + goto error2; + + strcpy (user_dir, home_dir); + strcat (user_dir, "/"); + } + else + { + user_dir = (char*) HeapAlloc (GetProcessHeap(), 0, strlen (p) + 1); + if (user_dir == NULL) + goto error2; + + *user_dir = 0; + } + + d = user_dir + strlen (user_dir); + while (*p && *p != '"') + { + if ((*p == '\\') && (*(p+1) != 0)) + p++; + *d++ = *p++; + } + *d = 0; + } +error2: + fclose (file); + + if (user_dir) + return user_dir; + + error: + if (fallback) + return strdup (fallback); + return NULL; +} + +/** + * xdg_user_dir_lookup: + * @type: a string specifying the type of directory + * @returns: a newly allocated absolute pathname + * + * Looks up a XDG user directory of the specified type. + * Example of types are "DESKTOP" and "DOWNLOAD". + * + * The return value is always != NULL (unless out of memory), + * and if a directory + * for the type is not specified by the user the default + * is the home directory. Except for DESKTOP which defaults + * to ~/Desktop. + * + * The return value is newly allocated and must be freed. + **/ +char * +xdg_user_dir_lookup (const char *type) +{ + char *dir, *home_dir, *user_dir; + + dir = xdg_user_dir_lookup_with_fallback (type, NULL); + if (dir != NULL) + return dir; + + home_dir = getenv ("HOME"); + + if (home_dir == NULL) + return strdup ("/tmp"); + + /* Special case desktop for historical compatibility */ + if (strcmp (type, "DESKTOP") == 0) + { + user_dir = (char*) HeapAlloc (GetProcessHeap(), 0, strlen (home_dir) + strlen ("/Desktop") + 1); + if (user_dir == NULL) + return NULL; + + strcpy (user_dir, home_dir); + strcat (user_dir, "/Desktop"); + return user_dir; + } + + return strdup (home_dir); +} diff --git a/dlls/shell32/xdg-user-dir-lookup.h b/dlls/shell32/xdg-user-dir-lookup.h new file mode 100644 index 0000000..ee247ff --- /dev/null +++ b/dlls/shell32/xdg-user-dir-lookup.h @@ -0,0 +1,22 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_XDG_USER_DIR_LOOKUP_H +#define __WINE_XDG_USER_DIR_LOOKUP_H + +char * xdg_user_dir_lookup (const char *type); + +#endif /* __WINE_XDG_USER_DIR_LOOKUP_H */ -- 1.4.1