Add missing files
authorJ. Ali Harlow <ali@juiblex.co.uk>
Fri, 17 Oct 2014 09:13:48 +0000 (10:13 +0100)
committerJ. Ali Harlow <ali@juiblex.co.uk>
Fri, 17 Oct 2014 09:13:48 +0000 (10:13 +0100)
librazor/path.c [new file with mode: 0644]
librazor/test-pfu.c [new file with mode: 0644]

diff --git a/librazor/path.c b/librazor/path.c
new file mode 100644 (file)
index 0000000..34b4a4e
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include "razor.h"
+#include "razor-internal.h"
+
+/**
+ * razor_path_add_root:
+ *
+ * Adds a root to a path. path must be an absolute pathname. In POSIX
+ * environments this is equivalent to the concationation of root and path.
+ * In Microsoft Windows an adjustment may need to be made for a drive letter
+ * in path (which will be dropped).
+ *
+ * Returns: The new pathname.
+ **/
+RAZOR_EXPORT char *razor_path_add_root(const char *path, const char *root)
+{
+       if (root && *root)
+               return razor_concat(root, SKIP_DRIVE_LETTER(path), NULL);
+       else
+               return strdup(path);
+}
+
+#if 0
+
+/*
+ * This should work, but for some reason PathCreateFromUrlW()
+ * treats the percent-encoded bytes as being in CP 850 rather
+ * than UTF-8 as expected even if we set the codepage.
+ */
+RAZOR_EXPORT char *razor_path_from_url(const char *url)
+{
+       UINT saved_cp;
+       HRESULT result;
+       DWORD len = MAX_PATH;
+       wchar_t *url16;
+       wchar_t path16[MAX_PATH];
+       char *path;
+
+       url16 = razor_utf8_to_utf16(url, -1);
+
+       saved_cp = GetConsoleCP();
+       SetConsoleCP(CP_UTF8);
+
+       result = PathCreateFromUrlW(url16, path16, &len, NULL);
+
+       SetConsoleCP(saved_cp);
+
+       if (result == S_OK)
+               path = razor_utf16_to_utf8(path16, len);
+       else
+               path = NULL;
+
+       free(url16);
+
+       return path;
+}
+
+#else
+
+#ifdef MSWIN_API
+static int is_ascii_letter(char c)
+{
+       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+#endif
+
+static int xdigit_value(char c)
+{
+       if (c >= '0' && c <= '9')
+               return c - '0';
+       else
+               return (c | 0x20) - 'a' + 10;
+}
+
+static int valid_unicode(unsigned unicode)
+{
+       /*
+        * Within the U+0000..U+10FFFF range defined by RFC3629
+        * but not in the U+D800..U+DFFF range prohibited in UTF-8.
+        */
+       return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000);
+}
+
+RAZOR_EXPORT char *razor_path_from_url(const char *url)
+{
+       int continuation_bytes = 0;
+       char *path, *p;
+       unsigned char c;
+       unsigned unicode;
+
+       if (strncmp(url, "file://", 7) == 0)
+               url += 7;
+       else
+               return NULL;
+
+       if (strncmp(url, "localhost/", 10) == 0)
+               url += 9;
+       else if (strncmp(url, "/", 1) != 0)
+               return NULL;
+
+#ifdef MSWIN_API
+       /*
+        * Under MS-Windows, file:///c:/xxx maps to c:/xxx
+        * Note that PathCreateFromUrl converts / to \ as well.
+        */
+       if (is_ascii_letter(url[1]) && url[2] == ':' && url[3] == '/')
+               url++;
+#endif
+
+       p = path = malloc(strlen(url) + 1);
+
+       while(*url) {
+               if (*url >= 0x7F || *url < 0x20) {
+                       free(path);
+                       return NULL;
+               } else if (*url != '%') {
+                       if (continuation_bytes) {
+                               free(path);
+                               return NULL;
+                       } else
+                               *p++ = *url++;
+               } else if (isxdigit(url[1]) && isxdigit(url[2])) {
+                       c = xdigit_value(url[1]) * 16 + xdigit_value(url[2]);
+                       if (c == '/') {
+                               free(path);
+                               return NULL;
+                       } else if (!continuation_bytes) {
+                               if (c >= 0xF5 || c == 0xC0 || c == 0xC1) {
+                                       free(path);
+                                       return NULL;
+                               } else if (c >= 0xF0) {
+                                       unicode = c & 7;
+                                       continuation_bytes = 3;
+                               } else if (c >= 0xE0) {
+                                       unicode = c & 3;
+                                       continuation_bytes = 2;
+                               } else if (c >= 0xC0) {
+                                       unicode = c & 1;
+                                       continuation_bytes = 1;
+                               }
+                       } else if ((c & 0xC0) != 0x80) {
+                               free(path);
+                               return NULL;
+                       } else {
+                               unicode <<= 6;
+                               unicode |= (c & 0x3F);
+
+                               if (!--continuation_bytes &&
+                                   !valid_unicode(unicode)) {
+                                       free(path);
+                                       return NULL;
+                               }
+                       }
+
+                       *p++ = c;
+                       url += 3;
+               } else {
+                       free(path);
+                       return NULL;
+               }
+       }
+
+       if (continuation_bytes) {
+               free(path);
+               return NULL;
+       }
+
+       *p++ = '\0';
+
+       return realloc(path, p - path);
+}
+
+#endif /* 0 */
diff --git a/librazor/test-pfu.c b/librazor/test-pfu.c
new file mode 100644 (file)
index 0000000..0414b38
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef MSWIN_API
+#include <windows.h>
+#endif
+#include "razor.h"
+
+int is_ascii_letter(char c)
+{
+       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+int is_slash(char c)
+{
+       return c == '/' || c == '\\';
+}
+
+const char *mswin_path(const char *path)
+{
+       if (path == NULL)
+               return NULL;
+
+       if (path[0] == '/' && is_ascii_letter(path[1]) && path[2] == ':' &&
+           path[3] == '/')
+               path++;
+
+       return path;
+}
+
+int path_cmp(const char *p1, const char *p2)
+{
+#ifdef MSWIN_API
+       while(*p1 && *p2) {
+               if (*p1 == *p2 || is_slash(*p1) && is_slash(*p2)) {
+                       p1++;
+                       p2++;
+               } else
+                       break;
+       }
+
+       return *p1 || *p2;
+#else
+       return strcmp(p1, p2);
+#endif
+}
+
+int test_pfu(const char *url, const char *path)
+{
+       char *s;
+       int r;
+
+       s = razor_path_from_url(url);
+
+#ifdef MSWIN_API
+       path = mswin_path(path);
+#endif
+
+       if (s && path)
+               r = path_cmp(s, path);
+       else
+               r = (s != path);
+
+       if (r) {
+               fprintf(stderr, "Fail: razor_path_from_url(\"%s\")", url);
+               if (s)
+                       fprintf(stderr, " returns \"%s\", expected", s);
+               else
+                       fprintf(stderr, " returns NULL, expected");
+               if (path)
+                       fprintf(stderr, " \"%s\"\n", path);
+               else
+                       fprintf(stderr, " NULL\n");
+       }
+
+       free(s);
+
+       return r;
+}
+
+#ifdef MSWIN_API
+UINT saved_cp;
+
+void cleanup_on_exit(void)
+{
+    SetConsoleOutputCP(saved_cp);
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+       int r = 0;
+
+#ifdef MSWIN_API
+       atexit(cleanup_on_exit);
+       saved_cp = GetConsoleOutputCP();
+       SetConsoleOutputCP(CP_UTF8);
+#endif
+
+       r |= test_pfu("file://localhost/etc/fstab", "/etc/fstab");
+       r |= test_pfu("file:///etc/fstab", "/etc/fstab");
+       r |= test_pfu("file://localhost/c:/WINDOWS/clock.avi",
+                     "/c:/WINDOWS/clock.avi");
+       r |= test_pfu("file:///c:/WINDOWS/clock.avi",
+                     "/c:/WINDOWS/clock.avi");
+       r |= test_pfu("file:///path/to/the%20file.txt",
+                     "/path/to/the file.txt");
+       r |= test_pfu("file:///home/s%C3%A9bastien", "/home/sébastien");
+       r |= test_pfu("file:///home/luk%C3%A1%C5%A1", "/home/lukáš");
+       r |= test_pfu("file:///var/log/22%20%e0%b8%aa%e0%b8%b4%e0%b8%87%e0%b8%ab%e0%b8%b2%e0%b8%84%e0%b8%a1%202014",
+                     "/var/log/22 สิงหาคม 2014");
+
+       exit(r ? 1 : 0);
+}