1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** @file
3  * TODO: insert short description here
4  *//*
5  * Authors: see git history
6  *
7  * Copyright (C) 2018 Authors
8  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9  */
10 #include <cstring>
11 #include <glib.h>
12 
13 #include "extract-uri.h"
14 
15 // FIXME: kill this ugliness when we have a proper CSS parser
16 
17 // Functions as per 4.3.4 of CSS 2.1
18 // http://www.w3.org/TR/CSS21/syndata.html#uri
extract_uri(char const * s,char const ** endptr)19 std::string extract_uri(char const *s, char const **endptr)
20 {
21     std::string result;
22 
23     if (!s)
24         return result;
25 
26     gchar const *sb = s;
27     if ( strlen(sb) < 4 || strncmp(sb, "url", 3) != 0 ) {
28         return result;
29     }
30 
31     sb += 3;
32 
33     if ( endptr ) {
34         *endptr = nullptr;
35     }
36 
37     // This first whitespace technically is not allowed.
38     // Just left in for now for legacy behavior.
39     while ( ( *sb == ' ' ) ||
40             ( *sb == '\t' ) )
41     {
42         sb++;
43     }
44 
45     if ( *sb == '(' ) {
46         sb++;
47         while ( ( *sb == ' ' ) ||
48                 ( *sb == '\t' ) )
49         {
50             sb++;
51         }
52 
53         gchar delim = ')';
54         if ( (*sb == '\'' || *sb == '"') ) {
55             delim = *sb;
56             sb++;
57         }
58 
59         if (!*sb) {
60             return result;
61         }
62 
63         gchar const* se = sb;
64         while ( *se && (*se != delim) ) {
65             se++;
66         }
67 
68         // we found the delimiter
69         if ( *se ) {
70             if ( delim == ')' ) {
71                 if ( endptr ) {
72                     *endptr = se + 1;
73                 }
74 
75                 // back up for any trailing whitespace
76                 while (se > sb && g_ascii_isspace(se[-1]))
77                 {
78                     se--;
79                 }
80 
81                 result = std::string(sb, se);
82             } else {
83                 gchar const* tail = se + 1;
84                 while ( ( *tail == ' ' ) ||
85                         ( *tail == '\t' ) )
86                 {
87                     tail++;
88                 }
89                 if ( *tail == ')' ) {
90                     if ( endptr ) {
91                         *endptr = tail + 1;
92                     }
93                     result = std::string(sb, se);
94                 }
95             }
96         }
97     }
98 
99     return result;
100 }
101 
102 /*
103   Local Variables:
104   mode:c++
105   c-file-style:"stroustrup"
106   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
107   indent-tabs-mode:nil
108   fill-column:99
109   End:
110 */
111 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
112