1
2 #include "config.h"
3
4 #include <string.h>
5 #include <fcitx-utils/utils.h>
6 #include <fcitx-utils/utf8.h>
7 #include <iconv.h>
8 #include <ctype.h>
9 #include "cloudpinyin.h"
10
ishex(char ch)11 static inline boolean ishex(char ch)
12 {
13 if ((ch >= '0' && ch <= '9') || (ch >='a' && ch <='f') || (ch >='A' && ch <='F'))
14 return true;
15 return false;
16 }
17
tohex(char ch)18 static inline unsigned char tohex(char ch)
19 {
20 if (ch >= '0' && ch <= '9')
21 return ch - '0';
22 if (ch >='a' && ch <='f')
23 return ch - 'a' + 10;
24 if (ch >='A' && ch <='F')
25 return ch - 'A' + 10;
26 return 0;
27 }
28
SogouParseKey(FcitxCloudPinyin * cloudpinyin,CurlQueue * queue)29 void SogouParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
30 {
31 char* str = fcitx_utils_trim(queue->str);
32 const char* ime_patch_key = "ime_patch_key = \"";
33 size_t len = strlen(str);
34 if (len == SOGOU_KEY_LENGTH + strlen(ime_patch_key) + 1
35 && strncmp(str, ime_patch_key, strlen(ime_patch_key)) == 0
36 && str[len - 1] == '\"') {
37 sscanf(str,"ime_patch_key = \"%s\"", cloudpinyin->key);
38 cloudpinyin->initialized = true;
39 cloudpinyin->key[SOGOU_KEY_LENGTH] = '\0';
40 }
41
42 free(str);
43 }
44
MapSogouStringToHalf(const char * string)45 char* MapSogouStringToHalf(const char* string)
46 {
47 const char* s = string;
48 const char* sn;
49 size_t len = strlen(string);
50 char* half = fcitx_utils_malloc0(sizeof(char) * (len + 1));
51 char* halfp = half;
52 int upperCount = 0;
53
54 while (*s) {
55 unsigned int chr = 0;
56
57 sn = fcitx_utf8_get_char(s, &chr);
58
59 /* from A to Z */
60 if ((chr >= 0xff21 && chr <= 0xff3a) || (chr >= 0xff41 && chr <= 0xff5a)) {
61 *halfp = (char) (chr & 0xff) + 0x20;
62 if (isupper(*halfp))
63 upperCount ++;
64 halfp ++;
65 }
66 else {
67 while(s < sn) {
68 *halfp = *s;
69 if (isupper(*halfp))
70 upperCount ++;
71 s++;
72 halfp++;
73 }
74 }
75
76 s = sn;
77 }
78 if (*half && isupper(*half) && upperCount == 1) {
79 *half = tolower(*half);
80 }
81 return half;
82 }
83
SogouParsePinyin(FcitxCloudPinyin * cloudpinyin,CurlQueue * queue)84 char* SogouParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
85 {
86 char *start = NULL, *end = NULL;
87 if ((start = strchr(queue->str, '"')) != NULL && (end = strstr(queue->str, "%EF%BC%9A")) != NULL)
88 {
89 start ++;
90 if (start < end)
91 {
92 size_t length = end - start;
93 int conv_length;
94 char *unescapedstring = curl_easy_unescape(queue->curl, start, length, &conv_length);
95 char *realstring = MapSogouStringToHalf(unescapedstring);
96 curl_free(unescapedstring);
97 return realstring;
98 }
99 }
100 return NULL;
101 }
102
QQParseKey(FcitxCloudPinyin * cloudpinyin,CurlQueue * queue)103 void QQParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
104 {
105 char* str = fcitx_utils_trim(queue->str);
106 const char* ime_patch_key = "{\"key\":\"";
107 if (strncmp(str, ime_patch_key, strlen(ime_patch_key)) == 0)
108 {
109 if (sscanf(str,"{\"key\":\"%32s\",\"ret\":\"suc\"}", cloudpinyin->key) > 0)
110 {
111 cloudpinyin->initialized = true;
112 cloudpinyin->key[QQ_KEY_LENGTH] = '\0';
113 }
114 }
115
116 free(str);
117 }
118
QQParsePinyin(FcitxCloudPinyin * cloudpinyin,CurlQueue * queue)119 char* QQParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
120 {
121 char *start = NULL, *end = NULL;
122 if ((start = strstr(queue->str, "\"rs\":[\"")) != NULL)
123 {
124 start += strlen( "\"rs\":[\"");
125 if ((end = strstr(start, "\"")) != NULL)
126 {
127 size_t length = end - start;
128 char *realstring = fcitx_utils_malloc0(sizeof(char) * (length + 1));
129 strncpy(realstring, start, length);
130 realstring[length] = '\0';
131 return realstring;
132 }
133 }
134 return NULL;
135 }
136
GoogleParsePinyin(FcitxCloudPinyin * cloudpinyin,CurlQueue * queue)137 char* GoogleParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
138 {
139 char *start = NULL, *end = NULL;
140 if ((start = strstr(queue->str, "\",[\"")) != NULL)
141 {
142 start += strlen( "\",[\"");
143 if ((end = strstr(start, "\"")) != NULL)
144 {
145 size_t length = end - start;
146 char *realstring = fcitx_utils_malloc0(sizeof(char) * (length + 1));
147 strncpy(realstring, start, length);
148 realstring[length] = '\0';
149 return realstring;
150 }
151 }
152 return NULL;
153 }
154
BaiduParsePinyin(FcitxCloudPinyin * cloudpinyin,CurlQueue * queue)155 char* BaiduParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
156 {
157 char *start = NULL, *end = NULL;
158 static iconv_t conv = 0;
159 if (conv == 0)
160 conv = iconv_open("utf-8", "utf-16be");
161
162 if (conv == (iconv_t)(-1))
163 return NULL;
164 if ((start = strstr(queue->str, "[[[\"")) != NULL)
165 {
166 start += strlen( "[[[\"");
167 if ((end = strstr(start, "\",")) != NULL)
168 {
169 size_t length = end - start;
170 if (length % 6 != 0 || length == 0)
171 return NULL;
172
173 size_t i = 0, j = 0;
174 char* buf = fcitx_utils_malloc0((length / 6 + 1) * 2);
175 while (i < length)
176 {
177 if (start[i] == '\\' && start[i+1] == 'u')
178 {
179 if (ishex(start[i+2]) && ishex(start[i+3]) && ishex(start[i+4]) && ishex(start[i+5]))
180 {
181 buf[j++] = (tohex(start[i+2]) << 4) | tohex(start[i+3]);
182 buf[j++] = (tohex(start[i+4]) << 4) | tohex(start[i+5]);
183 }
184 else
185 break;
186 }
187
188 i += 6;
189 }
190
191 if (i != length)
192 {
193 free(buf);
194 return NULL;
195 }
196 buf[j++] = 0;
197 buf[j++] = 0;
198 size_t len = UTF8_MAX_LENGTH * (length / 6) * sizeof(char);
199 char* realstring = fcitx_utils_malloc0(UTF8_MAX_LENGTH * (length / 6) * sizeof(char));
200 IconvStr p = buf; char *pp = realstring;
201 iconv(conv, &p, &j, &pp, &len);
202
203 free(buf);
204 if (fcitx_utf8_check_string(realstring))
205 return realstring;
206 else
207 {
208 free(realstring);
209 return NULL;
210 }
211 }
212 }
213 return NULL;
214 }
215