1 /*
2 * Copyright 2008 The qDecoder Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE QDECODER PROJECT ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE QDECODER PROJECT BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 /**
27 * @file qEncode.c Encoding/decoding API
28 */
29
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include "md5/md5.h"
38 #include "qDecoder.h"
39 #include "qInternal.h"
40
41 /**
42 * Parse URL encoded query string
43 *
44 * @param entry a pointer of Q_ENTRY structure. NULL can be used
45 * @param query URL encoded string
46 * @param equalchar separater of key, value pair
47 * @param sepchar separater of line
48 * @param count if count is not NULL, a number of parsed entries are stored
49 *
50 * @return a pointer of Q_ENTRY if successful, otherwise returns NULL
51 *
52 * @code
53 * cont char query = "category=love&str=%C5%A5%B5%F0%C4%DA%B4%F5&sort=asc";
54 * Q_ENTRY *entry = qDecodeQueryString(NULL, req->pszQueryString, '=', '&', NULL);
55 * printf("category = %s\n", entry->getStr(entry, "category"));
56 * printf("str = %s\n", entry->getStr(entry, "str"));
57 * printf("sort = %s\n", entry->getStr(entry, "sort"));
58 * entry->free(entry);
59 * @endcode
60 */
61 Q_ENTRY *qDecodeQueryString(Q_ENTRY *entry, const char *query, char equalchar, char sepchar, int *count) {
62 if(entry == NULL) {
63 entry = qEntry();
64 if(entry == NULL) return NULL;
65 }
66
67 char *newquery = NULL;
68 int cnt = 0;
69
70 if(query != NULL) newquery = strdup(query);
71 while (newquery && *newquery) {
72 char *value = _q_makeword(newquery, sepchar);
73 char *name = qStrTrim(_q_makeword(value, equalchar));
74 qDecodeUrl(name);
75 qDecodeUrl(value);
76
77 if(entry->putStr(entry, name, value, false) == true) cnt++;
78 free(name);
79 free(value);
80 }
81 if(newquery != NULL) free(newquery);
82 if(count != NULL) *count = cnt;
83
84 return entry;
85 }
86
87 /**
88 * Encode string as URL encoded string
89 *
90 * @param str a pointer of source string
91 *
92 * @return a malloced string pointer of URL encoded string in case of successful, otherwise returns NULL
93 *
94 * @code
95 * char encstr = qEncodeUrl("hello 'qDecoder' world");
96 * if(encstr != NULL) free(encstr);
97 * @endcode
98 */
99 char *qEncodeUrl(const char *str) {
100 char *encstr, buf[2+1];
101 unsigned char c;
102 int i, j;
103
104 if (str == NULL) return NULL;
105 if ((encstr = (char *)malloc((strlen(str) * 3) + 1)) == NULL) return NULL;
106
107 for (i = j = 0; str[i]; i++) {
108 c = (unsigned char)str[i];
109 if ((c >= '0') && (c <= '9')) encstr[j++] = c;
110 else if ((c >= 'A') && (c <= 'Z')) encstr[j++] = c;
111 else if ((c >= 'a') && (c <= 'z')) encstr[j++] = c;
112 else if ((c == '@') || (c == '.') || (c == '/') || (c == '\\')
113 || (c == '-') || (c == '_') || (c == ':') ) encstr[j++] = c;
114 else {
115 sprintf(buf, "%02x", c);
116 encstr[j++] = '%';
117 encstr[j++] = buf[0];
118 encstr[j++] = buf[1];
119 }
120 }
121 encstr[j] = '\0';
122
123 return encstr;
124 }
125
126 /**
127 * Parse URL encoded string
128 *
129 * @param str a pointer of URL encoded string
130 *
131 * @return a string pointer of str in case of successful, otherwise returns NULL
132 *
133 * @note
134 * This modify str directly
135 *
136 * @code
137 * char str[256] = "hello%20%27qDecoder%27%20world";
138 * printf("Before : %s\n", str);
139 * qDecodeUrl(str);
140 * printf("After : %s\n", str);
141 * @endcode
142 */
143 char *qDecodeUrl(char *str) {
144 int i, j;
145
146 if (!str) return NULL;
147 for (i = j = 0; str[j]; i++, j++) {
148 switch (str[j]) {
149 case '+': {
150 str[i] = ' ';
151 break;
152 }
153 case '%': {
154 str[i] = _q_x2c(str[j + 1], str[j + 2]);
155 j += 2;
156 break;
157 }
158 default: {
159 str[i] = str[j];
160 break;
161 }
162 }
163 }
164 str[i] = '\0';
165
166 return str;
167 }