1
by Evan Dandrea
Initial release. |
1 |
#include <libxml/parser.h> |
2 |
#include <libxml/tree.h> |
|
3 |
#include <stdio.h> |
|
4 |
#include <string.h> |
|
5 |
||
6 |
#include <sys/types.h> |
|
3
by Evan Dandrea
* Added tests for empty passwords, reserved usernames, bad usernames and |
7 |
#include <sys/stat.h> |
1
by Evan Dandrea
Initial release. |
8 |
#include <dirent.h> |
9 |
||
10 |
#include "gaim-import.h" |
|
11 |
#include "registry.h" |
|
12 |
#include "utils.h" |
|
13 |
||
14 |
xmlDoc* gaim_new_accounts_file(void) { |
|
15 |
static xmlDoc* doc = NULL; |
|
16 |
xmlNode* node = NULL; |
|
17 |
char* accounts_file; |
|
18 |
int opts = XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_RECOVER; |
|
19 |
||
20 |
if(!doc) { |
|
21 |
asprintf(&accounts_file, "%s/%s/%s/%s", to_location, |
|
22 |
"home", to_user, |
|
23 |
".gaim/accounts.xml"); |
|
24 |
||
25 |
create_file(accounts_file); |
|
26 |
doc = xmlReadFile(accounts_file, NULL, opts); |
|
27 |
free(accounts_file); |
|
28 |
||
29 |
node = xmlDocGetRootElement(doc); |
|
30 |
if(!node) { |
|
31 |
node = xmlNewNode(NULL, (xmlChar*) "accounts"); |
|
32 |
xmlNewProp(node, (xmlChar*) "version", (xmlChar*) "1.0"); |
|
33 |
xmlDocSetRootElement(doc, node); |
|
34 |
}
|
|
35 |
}
|
|
36 |
return doc; |
|
37 |
}
|
|
38 |
||
39 |
void gaim_save_accounts_file(void) { |
|
40 |
xmlDoc* doc = gaim_new_accounts_file(); |
|
41 |
char* accounts_file; |
|
42 |
asprintf(&accounts_file, "%s/%s/%s/%s", to_location, |
|
43 |
"home", to_user, |
|
44 |
".gaim/accounts.xml"); |
|
45 |
xmlSaveFormatFile(accounts_file, doc, 1); |
|
46 |
}
|
|
47 |
||
48 |
int gaim_account_exists(xmlNode* node) { |
|
49 |
xmlNode* ptr = NULL; |
|
50 |
xmlDoc* doc = NULL; |
|
51 |
xmlChar* username = NULL; |
|
52 |
xmlChar* protocol = NULL; |
|
53 |
||
54 |
node = node->children; |
|
55 |
||
56 |
while(node != NULL) { |
|
57 |
if(xmlStrcmp(node->name, (xmlChar*) "name") == 0) |
|
58 |
username = node->children->content; |
|
59 |
else if(xmlStrcmp(node->name, (xmlChar*) "protocol") == 0) |
|
60 |
protocol = node->children->content; |
|
61 |
||
62 |
node = node->next; |
|
63 |
}
|
|
64 |
||
65 |
doc = gaim_new_accounts_file(); |
|
66 |
node = xmlDocGetRootElement(doc); |
|
67 |
||
68 |
node = node->children; |
|
69 |
int found = 0; |
|
70 |
||
71 |
// For each account.
|
|
72 |
while(node) { |
|
73 |
if(node->type == XML_ELEMENT_NODE && |
|
74 |
(xmlStrcmp(node->name, (xmlChar*) "account") == 0)) { |
|
75 |
||
76 |
ptr = node->children; |
|
77 |
||
78 |
// For each account property.
|
|
79 |
while(ptr != NULL) { |
|
80 |
if(xmlStrcmp(ptr->name, (xmlChar*) "name") == 0) { |
|
81 |
if(xmlStrcmp(ptr->children->content, |
|
82 |
(xmlChar*) username) == 0) { |
|
83 |
found++; |
|
84 |
}
|
|
85 |
}
|
|
86 |
if(xmlStrcmp(ptr->name, (xmlChar*) "protocol") == 0) { |
|
87 |
if(xmlStrcmp(ptr->children->content, |
|
88 |
(xmlChar*) protocol) == 0) { |
|
89 |
found++; |
|
90 |
}
|
|
91 |
}
|
|
92 |
ptr = ptr->next; |
|
93 |
}
|
|
94 |
||
95 |
if(found == 2) return 1; |
|
96 |
found = 0; |
|
97 |
}
|
|
98 |
node = node->next; |
|
99 |
}
|
|
100 |
return 0; |
|
101 |
}
|
|
102 |
||
103 |
void gaim_add_account(xmlNode* node) { |
|
104 |
xmlDoc* doc = gaim_new_accounts_file(); |
|
105 |
xmlNode* top = xmlDocGetRootElement(doc); |
|
106 |
xmlAddChild(top, node); |
|
107 |
}
|
|
108 |
||
109 |
void gaim_import_gaim(void) { |
|
110 |
xmlDoc* doc = NULL; |
|
111 |
xmlNode* node, *node_copy = NULL; |
|
112 |
char* accounts_file; |
|
113 |
||
6
by Evan Dandrea
* Added proper support for the Windows registry's use of UTF-16 strings. |
114 |
char* filename, *path; |
115 |
char* appdata = NULL; |
|
116 |
||
1
by Evan Dandrea
Initial release. |
117 |
if(os_type == LINUX) |
118 |
asprintf(&accounts_file, "%s/%s/%s/%s", from_location, |
|
119 |
"home", from_user, |
|
120 |
".gaim/accounts.xml"); |
|
6
by Evan Dandrea
* Added proper support for the Windows registry's use of UTF-16 strings. |
121 |
else if(os_type == WINDOWSXP) { |
122 |
asprintf(&filename, "%s/%s/%s/%s", from_location, |
|
123 |
"Documents and Settings", from_user, "NTUSER.DAT"); |
|
124 |
appdata = findkey(filename, "\\Software\\Microsoft\\Windows\\" |
|
125 |
"CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); |
|
126 |
free(filename); |
|
127 |
if(!appdata) { |
|
128 |
printf("Couldn't find %s\n", appdata); |
|
129 |
return; |
|
130 |
}
|
|
131 |
path = reformat_path(appdata); |
|
132 |
free(appdata); |
|
133 |
asprintf(&accounts_file, "%s/%s/%s", from_location, path, |
|
134 |
"/.gaim/accounts.xml"); |
|
135 |
free(path); |
|
136 |
}
|
|
1
by Evan Dandrea
Initial release. |
137 |
|
138 |
if(!accounts_file) return; |
|
139 |
||
140 |
doc = xmlReadFile(accounts_file, NULL, XML_PARSE_NOBLANKS); |
|
141 |
free(accounts_file); |
|
3
by Evan Dandrea
* Added tests for empty passwords, reserved usernames, bad usernames and |
142 |
if(!doc) return; |
1
by Evan Dandrea
Initial release. |
143 |
node = xmlDocGetRootElement(doc); |
144 |
||
145 |
node = node->children; |
|
146 |
||
147 |
while(node) { |
|
148 |
if(node->type == XML_ELEMENT_NODE && |
|
149 |
(xmlStrcmp(node->name, (xmlChar*) "account") == 0)) { |
|
150 |
||
151 |
if(!gaim_account_exists(node)) { |
|
152 |
node_copy = xmlCopyNode(node, 1); |
|
153 |
gaim_add_account(node_copy); |
|
154 |
}
|
|
155 |
}
|
|
156 |
node = node->next; |
|
157 |
}
|
|
158 |
gaim_save_accounts_file(); |
|
159 |
}
|
|
160 |
||
161 |
void gaim_import_other(const char* proto, const char* username, |
|
162 |
const char* password) { |
|
163 |
||
164 |
xmlNode *account, *name, *protocol; |
|
165 |
account = xmlNewNode(NULL, (xmlChar*) "account"); |
|
166 |
||
167 |
// protocol must come before name in the accounts file otherwise Gaim will
|
|
168 |
// have a bad time.
|
|
169 |
protocol = xmlNewChild(account, NULL, (xmlChar*) "protocol", (xmlChar*) proto); |
|
170 |
name = xmlNewChild(account, NULL, (xmlChar*) "name", (xmlChar*) username); |
|
171 |
||
172 |
if(!gaim_account_exists(account)) |
|
173 |
gaim_add_account(account); |
|
174 |
}
|
|
175 |
||
176 |
void gaim_import_yahoo(void) { |
|
177 |
char* username; |
|
178 |
char* filename; |
|
179 |
||
180 |
asprintf(&filename, "%s/%s/%s/%s", from_location, |
|
181 |
"Documents and Settings", from_user, "NTUSER.DAT"); |
|
182 |
username = findkey(filename, |
|
183 |
"\\Software\\Yahoo\\pager\\Yahoo! User ID"); |
|
184 |
free(filename); |
|
185 |
||
186 |
if(username) { |
|
187 |
gaim_import_other("prpl-yahoo", username, NULL); |
|
188 |
free(username); |
|
189 |
gaim_save_accounts_file(); |
|
190 |
} else { |
|
191 |
puts("could not get yahoo ID from registry."); |
|
192 |
exit(EXIT_FAILURE); |
|
193 |
}
|
|
194 |
}
|
|
195 |
||
196 |
// FIXME: This is a terrible test. If the user has an AIM account with the
|
|
197 |
// same username as the one they use for Windows, the test will fail.
|
|
198 |
void gaim_import_aimtriton(void) { |
|
199 |
DIR *dir, *dir2; |
|
200 |
struct dirent *entry, *entry2; |
|
3
by Evan Dandrea
* Added tests for empty passwords, reserved usernames, bad usernames and |
201 |
struct stat buf; |
6
by Evan Dandrea
* Added proper support for the Windows registry's use of UTF-16 strings. |
202 |
char* dirname, *uprofile, *filename, *cls, *path; |
203 |
char* appdata = NULL; |
|
204 |
||
205 |
asprintf(&filename, "%s/%s/%s/%s", from_location, |
|
206 |
"Documents and Settings", from_user, "NTUSER.DAT"); |
|
207 |
appdata = findkey(filename, "\\Software\\Microsoft\\Windows\\" |
|
208 |
"CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); |
|
209 |
free(filename); |
|
210 |
if(!appdata) { |
|
211 |
printf("Couldn't find %s\n", appdata); |
|
212 |
return; |
|
213 |
}
|
|
214 |
path = reformat_path(appdata); |
|
215 |
free(appdata); |
|
216 |
asprintf(&dirname, "%s/%s/%s", from_location, path, "AOL/UserProfiles"); |
|
217 |
free(path); |
|
218 |
||
1
by Evan Dandrea
Initial release. |
219 |
dir = opendir(dirname); |
3
by Evan Dandrea
* Added tests for empty passwords, reserved usernames, bad usernames and |
220 |
if(!dir) { |
6
by Evan Dandrea
* Added proper support for the Windows registry's use of UTF-16 strings. |
221 |
printf("Could not open AIM profile root directory: %s\n", dirname); |
3
by Evan Dandrea
* Added tests for empty passwords, reserved usernames, bad usernames and |
222 |
free(dirname); |
223 |
return; |
|
6
by Evan Dandrea
* Added proper support for the Windows registry's use of UTF-16 strings. |
224 |
}
|
225 |
||
226 |
while((entry = readdir(dir)) != NULL) { |
|
227 |
if(entry->d_type != DT_DIR) |
|
228 |
continue; |
|
229 |
||
230 |
if(strcmp(entry->d_name,"All Users") == 0 || |
|
231 |
(strcmp(entry->d_name,".") == 0 || |
|
232 |
strcmp(entry->d_name,"..") == 0)) { |
|
233 |
continue; |
|
234 |
}
|
|
235 |
||
236 |
asprintf(&uprofile, "%s/%s", dirname, entry->d_name); |
|
237 |
dir2 = opendir(uprofile); |
|
238 |
if(!dir2) { |
|
239 |
printf("Could not open user's AIM profile directory: %s\n", uprofile); |
|
240 |
free(uprofile); |
|
241 |
return; |
|
242 |
}
|
|
243 |
||
244 |
while((entry2 = readdir(dir2)) != NULL) { |
|
245 |
if((strcmp(entry2->d_name,from_user) != 0) && |
|
246 |
((strcmp(entry2->d_name,".") != 0) && |
|
247 |
(strcmp(entry2->d_name,"..") != 0))) { |
|
248 |
asprintf(&cls, "%s/%s/cls", uprofile, entry2->d_name); |
|
249 |
||
250 |
if(stat(cls, &buf) == 0) |
|
251 |
gaim_import_other("prpl-oscar", entry2->d_name, NULL); |
|
252 |
||
253 |
free(cls); |
|
254 |
}
|
|
255 |
}
|
|
256 |
closedir(dir2); |
|
257 |
free(uprofile); |
|
258 |
||
259 |
}
|
|
260 |
free(dirname); |
|
1
by Evan Dandrea
Initial release. |
261 |
closedir(dir); |
262 |
gaim_save_accounts_file(); |
|
263 |
}
|