1/**
2 * \file pathutils.c
3 *
4 * Copyright (C) 2005-2008 Linus Walleij <triad@df.lth.se>
5 * Copyright (C) 2006 Chris A. Debenham <chris@adebenham.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22#include "common.h"
23#include "pathutils.h"
24#include <stdlib.h>
25#include <limits.h>
26#include <string.h>
27#include <libgen.h>
28
29/* Find the folder_id of a given path
30 * Runs by walking through folders structure */
31static uint32_t
32lookup_folder_id (LIBMTP_folder_t * folder, char * path, char * parent)
33{
34  char * current;
35  uint32_t ret = (uint32_t) -1;
36
37  if (strcmp(path,"/")==0)
38    return 0;
39
40  if (folder == NULL) {
41    return ret;
42  }
43
44  current = malloc (strlen(parent) + strlen(folder->name) + 2);
45  sprintf(current,"%s/%s",parent,folder->name);
46  if (strcasecmp (path, current) == 0) {
47    free (current);
48    return folder->folder_id;
49  }
50  if (strncasecmp (path, current, strlen (current)) == 0) {
51    ret = lookup_folder_id (folder->child, path, current);
52  }
53  free (current);
54  if (ret != (uint32_t) (-1)) {
55    return ret;
56  }
57  ret = lookup_folder_id (folder->sibling, path, parent);
58  return ret;
59}
60
61/* Parses a string to find item_id */
62int
63parse_path (char * path, LIBMTP_file_t * files, LIBMTP_folder_t * folders)
64{
65  char *rest;
66  uint32_t item_id;
67
68  // Check if path is an item_id
69  if (*path != '/') {
70    item_id = strtoul(path, &rest, 0);
71    // really should check contents of "rest" here...
72    /* if not number, assume a file name */
73    if (item_id == 0) {
74      LIBMTP_file_t * file = files;
75
76      /* search for matching name */
77      while (file != NULL) {
78	if (strcasecmp (file->filename, path) == 0) {
79	  return file->item_id;
80	}
81	file = file->next;
82      }
83    }
84    return item_id;
85  }
86  // Check if path is a folder
87  item_id = lookup_folder_id(folders,path,"");
88  if (item_id == (uint32_t) -1) {
89    char * dirc = strdup(path);
90    char * basec = strdup(path);
91    char * parent = dirname(dirc);
92    char * filename = basename(basec);
93    uint32_t parent_id = lookup_folder_id(folders,parent,"");
94    LIBMTP_file_t * file;
95
96    file = files;
97    while (file != NULL) {
98      if (file->parent_id == parent_id) {
99        if (strcasecmp (file->filename, filename) == 0) {
100	  free(dirc);
101	  free(basec);
102          return file->item_id;
103        }
104      }
105      file = file->next;
106    }
107    free(dirc);
108    free(basec);
109  } else {
110    return item_id;
111  }
112
113  return -1;
114}
115
116int progress (const uint64_t sent, const uint64_t total, void const * const data)
117{
118  int percent = (sent*100)/total;
119#ifdef __WIN32__
120  printf("Progress: %I64u of %I64u (%d%%)\r", sent, total, percent);
121#else
122  printf("Progress: %llu of %llu (%d%%)\r", sent, total, percent);
123#endif
124  fflush(stdout);
125  return 0;
126}
127
128/* Find the file type based on extension */
129LIBMTP_filetype_t
130find_filetype (const char * filename)
131{
132  char *ptype;
133  LIBMTP_filetype_t filetype;
134
135#ifdef __WIN32__
136  ptype = strrchr(filename, '.');
137#else
138  ptype = rindex(filename,'.');
139#endif
140  // This accounts for the case with a filename without any "." (period).
141  if (!ptype) {
142    ptype = "";
143  } else {
144    ++ptype;
145  }
146
147  /* This need to be kept constantly updated as new file types arrive. */
148  if (!strcasecmp (ptype, "wav")) {
149    filetype = LIBMTP_FILETYPE_WAV;
150  } else if (!strcasecmp (ptype, "mp3")) {
151    filetype = LIBMTP_FILETYPE_MP3;
152  } else if (!strcasecmp (ptype, "wma")) {
153    filetype = LIBMTP_FILETYPE_WMA;
154  } else if (!strcasecmp (ptype, "ogg")) {
155    filetype = LIBMTP_FILETYPE_OGG;
156  } else if (!strcasecmp (ptype, "mp4")) {
157    filetype = LIBMTP_FILETYPE_MP4;
158  } else if (!strcasecmp (ptype, "wmv")) {
159    filetype = LIBMTP_FILETYPE_WMV;
160  } else if (!strcasecmp (ptype, "avi")) {
161    filetype = LIBMTP_FILETYPE_AVI;
162  } else if (!strcasecmp (ptype, "mpeg") || !strcasecmp (ptype, "mpg")) {
163    filetype = LIBMTP_FILETYPE_MPEG;
164  } else if (!strcasecmp (ptype, "asf")) {
165    filetype = LIBMTP_FILETYPE_ASF;
166  } else if (!strcasecmp (ptype, "qt") || !strcasecmp (ptype, "mov")) {
167    filetype = LIBMTP_FILETYPE_QT;
168  } else if (!strcasecmp (ptype, "wma")) {
169    filetype = LIBMTP_FILETYPE_WMA;
170  } else if (!strcasecmp (ptype, "jpg") || !strcasecmp (ptype, "jpeg")) {
171    filetype = LIBMTP_FILETYPE_JPEG;
172  } else if (!strcasecmp (ptype, "jfif")) {
173    filetype = LIBMTP_FILETYPE_JFIF;
174  } else if (!strcasecmp (ptype, "tif") || !strcasecmp (ptype, "tiff")) {
175    filetype = LIBMTP_FILETYPE_TIFF;
176  } else if (!strcasecmp (ptype, "bmp")) {
177    filetype = LIBMTP_FILETYPE_BMP;
178  } else if (!strcasecmp (ptype, "gif")) {
179    filetype = LIBMTP_FILETYPE_GIF;
180  } else if (!strcasecmp (ptype, "pic") || !strcasecmp (ptype, "pict")) {
181    filetype = LIBMTP_FILETYPE_PICT;
182  } else if (!strcasecmp (ptype, "png")) {
183    filetype = LIBMTP_FILETYPE_PNG;
184  } else if (!strcasecmp (ptype, "wmf")) {
185    filetype = LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT;
186  } else if (!strcasecmp (ptype, "ics")) {
187    filetype = LIBMTP_FILETYPE_VCALENDAR2;
188  } else if (!strcasecmp (ptype, "exe") || !strcasecmp (ptype, "com") ||
189	     !strcasecmp (ptype, "bat") || !strcasecmp (ptype, "dll") ||
190	     !strcasecmp (ptype, "sys")) {
191    filetype = LIBMTP_FILETYPE_WINEXEC;
192  } else if (!strcasecmp (ptype, "aac")) {
193    filetype = LIBMTP_FILETYPE_AAC;
194  } else if (!strcasecmp (ptype, "mp2")) {
195    filetype = LIBMTP_FILETYPE_MP2;
196  } else if (!strcasecmp (ptype, "flac")) {
197    filetype = LIBMTP_FILETYPE_FLAC;
198  } else if (!strcasecmp (ptype, "m4a")) {
199    filetype = LIBMTP_FILETYPE_M4A;
200  } else if (!strcasecmp (ptype, "doc")) {
201    filetype = LIBMTP_FILETYPE_DOC;
202  } else if (!strcasecmp (ptype, "xml")) {
203    filetype = LIBMTP_FILETYPE_XML;
204  } else if (!strcasecmp (ptype, "xls")) {
205    filetype = LIBMTP_FILETYPE_XLS;
206  } else if (!strcasecmp (ptype, "ppt")) {
207    filetype = LIBMTP_FILETYPE_PPT;
208  } else if (!strcasecmp (ptype, "mht")) {
209    filetype = LIBMTP_FILETYPE_MHT;
210  } else if (!strcasecmp (ptype, "jp2")) {
211    filetype = LIBMTP_FILETYPE_JP2;
212  } else if (!strcasecmp (ptype, "jpx")) {
213    filetype = LIBMTP_FILETYPE_JPX;
214  } else if (!strcasecmp (ptype, "bin")) {
215    filetype = LIBMTP_FILETYPE_FIRMWARE;
216  } else if (!strcasecmp (ptype, "vcf")) {
217    filetype = LIBMTP_FILETYPE_VCARD3;
218  } else {
219    /* Tagging as unknown file type */
220    filetype = LIBMTP_FILETYPE_UNKNOWN;
221  }
222  printf("type: %s, %d\n", ptype, filetype);
223  return filetype;
224}
225
226/* Function that compensate for missing libgen.h on Windows */
227#ifndef HAVE_LIBGEN_H
228static char *basename(char *in) {
229  char *p;
230
231  if (in == NULL)
232    return NULL;
233  p = in + strlen(in) - 1;
234  while (*p != '\\' && *p != '/' && *p != ':')
235    { p--; }
236  return ++p;
237}
238#endif
239