[evolution-data-server/gnome-3-38] I#272 - WebDAV: Decode URI-s before comparing them



commit 74fa03dc54b9c6e60bdcf6264cbb40da50677b6f
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 19 15:04:12 2020 +0100

    I#272 - WebDAV: Decode URI-s before comparing them
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/272

 src/libedataserver/e-webdav-session.c      | 71 ++++++++++++++++++++++++++++--
 tests/libedataserver/libedataserver-test.c | 22 +++++++--
 2 files changed, 86 insertions(+), 7 deletions(-)
---
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index 768eaeb0e..8400f8476 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -5139,6 +5139,65 @@ e_webdav_session_util_free_privileges (GNode *privileges)
        g_node_destroy (privileges);
 }
 
+static gint
+e_webdav_session_uricmp (const gchar *str1,
+                        const gchar *str2,
+                        gint len,
+                        gboolean case_sensitive)
+{
+       const gchar *p1, *p2;
+       gchar c1, c2;
+       gint len1, len2;
+
+       g_return_val_if_fail (len >= 0, -1);
+       g_return_val_if_fail (str1 != NULL, -1);
+       g_return_val_if_fail (str2 != NULL, -1);
+
+       if (!len)
+               return 0;
+
+       /* Decode %-encoded letters, if needed */
+       #define get_next_char(str, ll, cc) G_STMT_START { \
+               if (!*str) { \
+                       cc = 0; \
+               } else if (*str == '%' && ll >= 2 && g_ascii_isxdigit (str[1]) && g_ascii_isxdigit (str[2])) 
{ \
+                       cc = ((str[1] >= '0' && str[1] <= '9') ? (str[1] - '0') : \
+                             (str[1] >= 'a' && str[1] <= 'f') ? (str[1] - 'a' + 10) : \
+                             (str[1] >= 'A' && str[1] <= 'F') ? (str[1] - 'A' + 10) : 0) * 16 + \
+                            ((str[2] >= '0' && str[2] <= '9') ? (str[2] - '0') : \
+                             (str[2] >= 'a' && str[2] <= 'f') ? (str[2] - 'a' + 10) : \
+                             (str[2] >= 'A' && str[2] <= 'F') ? (str[2] - 'A' + 10) : 0); \
+                       str += 3; \
+                       ll -= 3; \
+               } else { \
+                       cc = *str; \
+                       str++; \
+                       ll--; \
+               } \
+       } G_STMT_END
+
+       p1 = str1;
+       p2 = str2;
+
+       len1 = len;
+       len2 = len;
+
+       c1 = *p1;
+       c2 = *p2;
+
+       while (len1 > 0 && len2 > 0 && *p1 && *p2) {
+               get_next_char (p1, len1, c1);
+               get_next_char (p2, len2, c2);
+
+               if ((case_sensitive && c1 != c2) || (!case_sensitive && g_ascii_tolower (c1) != 
g_ascii_tolower (c2)))
+                       break;
+       }
+
+       #undef get_next_char
+
+       return c1 - c2;
+}
+
 /**
  * e_webdav_session_util_item_href_equal:
  * @href1: the first href
@@ -5200,18 +5259,22 @@ e_webdav_session_util_item_href_equal (const gchar *href1,
 
                /* it's the hostname part */
                if (from1 == href1) {
+                       const gchar *dash;
+
                        /* ignore the username/password part */
                        ptr = strchr (from1, '@');
-                       if (ptr)
+                       dash = strchr (from1, '/');
+                       if (ptr && (!dash || dash > ptr))
                                from1 = ptr + 1;
 
                        ptr = strchr (from2, '@');
-                       if (ptr)
+                       dash = strchr (from2, '/');
+                       if (ptr && (!dash || dash > ptr))
                                from2 = ptr + 1;
 
-                       if (g_ascii_strncasecmp (from1, from2, len) != 0)
+                       if (e_webdav_session_uricmp (from1, from2, len, FALSE) != 0)
                                return FALSE;
-               } else if (strncmp (from1, from2, len) != 0) {
+               } else if (e_webdav_session_uricmp (from1, from2, len, TRUE) != 0) {
                        return FALSE;
                }
        }
diff --git a/tests/libedataserver/libedataserver-test.c b/tests/libedataserver/libedataserver-test.c
index 8ff11b999..c3c225b62 100644
--- a/tests/libedataserver/libedataserver-test.c
+++ b/tests/libedataserver/libedataserver-test.c
@@ -28,7 +28,7 @@ test_webdav_href_compare (ETestServerFixture *fixture,
                const gchar *href2;
                gboolean same;
        } hrefs[] = {
-               { "http://www.gnome.org/";, "http://www.gnome.org/";, TRUE },
+       /* 0 */ { "http://www.gnome.org/";, "http://www.gnome.org/";, TRUE },
                { "https://www.gnome.org/";, "http://www.gnome.org/";, TRUE },
                { "http://user www gnome org/", "https://www.gnome.org/";, TRUE },
                { "http://www.gnome.org/index";, "http://www.gnome.org/";, FALSE },
@@ -38,7 +38,7 @@ test_webdav_href_compare (ETestServerFixture *fixture,
                { "http://www.gnome.org/path/collection/data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, TRUE },
                { "https://www.gnome.org/path/collection/data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, TRUE },
                { "http://user www gnome org/path/collection/data.ext", 
"http://www.gnome.org/path/collection/data.ext";, TRUE },
-               { "http://www.gnome.org/Path/collection/data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, FALSE },
+       /* 10 */{ "http://www.gnome.org/Path/collection/data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, FALSE },
                { "http://www.gnome.org/path/Collection/data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, FALSE },
                { "http://www.gnome.org/path/collection/Data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, FALSE },
                { "http://www.GNOME.org/path/collection/data.ext";, 
"http://www.gnome.org/path/collection/data.ext";, TRUE },
@@ -48,7 +48,23 @@ test_webdav_href_compare (ETestServerFixture *fixture,
                { "https://www.gnome.org/path";, "https://www.gnome.org/path/collection/data.ext";, FALSE },
                { "https://www.gnome.org/path/";, "https://www.gnome.org/path/collection/data.ext";, FALSE },
                { "https://www.gnome.org/path/collection";, "https://www.gnome.org/path/collection/data.ext";, 
FALSE },
-               { "https://www.gnome.org/path/collection/";, "https://www.gnome.org/path/collection/data.ext";, 
FALSE }
+       /* 20 */{ "https://www.gnome.org/path/collection/";, "https://www.gnome.org/path/collection/data.ext";, 
FALSE },
+               { "https://www.gnome.org/path/user@no.where/";, "http://www.gnome.org/path/user@no.where/";, 
TRUE },
+               { "https://www.gnome.org/path/user%40no.where/";, "http://www.gnome.org/path/user@no.where/";, 
TRUE },
+               { "https://www.gnome.org/path/user%40no.where/";, "http://www.gnome.org/path/user@no.where";, 
FALSE },
+               { "https://www.gnome.org/user%40no.where/";, "http://www.gnome.org/path/user@no.where";, FALSE 
},
+               { "https://www.gnome.org/user%40no.where";, "http://www.gnome.org/user%40no%2Ewhere";, TRUE },
+               { "https://www.gnome.org/user%40no.where";, "http://www.gnome.org/user%40no%2ewhere";, TRUE },
+               { "https://www.gnome.org/path/user%40no.where/path";, 
"http://www.gnome.org/path/user%40no%2Ewhere/path";, TRUE },
+               { "https://user www gnome org/path/user%40no.where/path", 
"http://www.gnome.org/path/user%40no%2Ewhere/path";, TRUE },
+               { "https://user www gnome org/path/user%40no.where/path", 
"http://www.gnome.org/path/user%40no%2Ewhere/path";, TRUE },
+       /* 30 */{ "https://user www gnome org/path/user@no.where/path", 
"http://www.gnome.org/path/user%40no%2Ewhere/path";, TRUE },
+               { "https://user www gnome org/path/user@no.where/path", "http://no www gnome 
org/path/user@no%2Ewhere/path", TRUE },
+               { "https://www.gnome.org/path%";, "https://www.gnome.org/path%";, TRUE },
+               { "https://www.gnome.org/path%g";, "https://www.gnome.org/path%g";, TRUE },
+               { "https://www.gnome.org/path%ah";, "https://www.gnome.org/path%ah";, TRUE },
+               { "https://www.gnome.org/path%32";, "https://www.gnome.org/path%32";, TRUE },
+               { "https://www.gnome.org/path%20%2e";, "https://www.gnome.org/path .", TRUE }
        };
        gint ii;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]