OSDN Git Service

b0cfbdf098b9aef95ea000f8b4db01fbce027891
[ntch/develop.git] / src / cloud / nt_cloud.c
1 /* Copyright 2013 Akira Ohta (akohta001@gmail.com)
2     This file is part of ntch.
3
4     The ntch is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 3 of the License, or
7     (at your option) any later version.
8
9     The ntch is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with ntch.  If not, see <http://www.gnu.org/licenses/>.
16     
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <locale.h>
22 #include <assert.h>
23 #include <wchar.h>
24 #include <iconv.h>
25 #include <errno.h>
26
27 #include "env.h"
28 #include "utils/nt_std_t.h"
29 #include "utils/text.h"
30 #include "utils/file.h"
31 #include "utils/base64.h"
32 #include "utils/crypt.h"
33 #include "utils/nt_conv_char.h"
34 #include "net/nt_http.h"
35 #include "cloud/nt_cloud.h"
36
37
38 #define NT_CLOUD_CHK_SUM (1478428)
39
40 typedef struct tag_nt_cloud_t *nt_cloud_tp;
41 typedef struct tag_nt_cloud_t {
42         nt_cloud_handle_t handle;
43         int ref_count;
44         char *usr_id;
45         char *passwd;
46         char *auth_url;
47         char *query_url;
48         char *home_url;
49         char *token;
50         int error_no;
51 }nt_cloud_t;
52
53
54 static nt_link_tp nt_split_line(char *data);
55 static int nt_get_cloud_result(const char *ptr);
56 static BOOL nt_cloud_edit_lines_file(nt_cloud_handle handle,
57                 const char *file_name, nt_link_tp lines, const char *php_file, int depth);
58 static BOOL nt_cloud_upload_file_local(nt_cloud_handle handle,
59                 const char *file_name, nt_link_tp lines, int depth);
60
61 nt_cloud_handle nt_cloud_init(
62                 const char *auth_url, const char *usr_id, const char *pass)
63 {
64         nt_cloud_tp cloudp;
65         
66         assert(usr_id && pass);
67         
68         cloudp = malloc(sizeof(nt_cloud_t));
69         if(!cloudp)
70                 return NULL;
71         cloudp->handle.chk_sum = NT_CLOUD_CHK_SUM;
72         cloudp->ref_count = 1;
73         cloudp->usr_id = nt_str_clone(usr_id);
74         if(!cloudp->usr_id){
75                 free(cloudp);
76                 return NULL;
77         }
78         cloudp->passwd = nt_str_clone(pass);
79         if(!cloudp->passwd){
80                 free(cloudp->usr_id);
81                 free(cloudp);
82                 return NULL;
83         }
84         cloudp->auth_url = nt_str_clone(auth_url);
85         if(!cloudp->auth_url){
86                 free(cloudp->passwd);
87                 free(cloudp->usr_id);
88                 free(cloudp);
89                 return NULL;
90         }
91         cloudp->query_url = NULL;
92         cloudp->home_url = NULL;
93         cloudp->token = NULL;
94         cloudp->error_no = 0;
95         if(!nt_cloud_chk_user(&cloudp->handle)){
96                 nt_cloud_release_ref(&cloudp->handle);
97                 return NULL;
98         }
99         
100         return &cloudp->handle;
101 }
102
103 int nt_cloud_add_ref(nt_cloud_handle handle)
104 {
105         nt_cloud_tp cloudp;
106         assert(handle);
107         assert(handle->chk_sum == NT_CLOUD_CHK_SUM);
108         cloudp = (nt_cloud_tp)handle;
109         assert(0 < cloudp->ref_count);
110         return ++cloudp->ref_count;
111 }
112 int nt_cloud_release_ref(nt_cloud_handle handle)
113 {
114         nt_cloud_tp cloudp;
115         assert(handle);
116         assert(handle->chk_sum == NT_CLOUD_CHK_SUM);
117         cloudp = (nt_cloud_tp)handle;
118         assert(0 < cloudp->ref_count);
119         if(0 != --cloudp->ref_count)
120                 return cloudp->ref_count;
121         assert(cloudp->usr_id);
122         free(cloudp->usr_id);
123         assert(cloudp->passwd);
124         free(cloudp->passwd);
125         assert(cloudp->auth_url);
126         free(cloudp->auth_url);
127         if(cloudp->query_url)
128                 free(cloudp->query_url);
129         if(cloudp->home_url)
130                 free(cloudp->home_url);
131         if(cloudp->token)
132                 free(cloudp->token);
133         free(cloudp);
134         return 0;
135 }
136
137 BOOL nt_cloud_chk_user(nt_cloud_handle handle)
138 {
139         char buf[1024];
140         char post_data[1024];
141         nt_cloud_tp cloudp;
142         nt_link_tp linkp, wrkp;
143         int idx;
144         
145         assert(handle);
146         assert(handle->chk_sum == NT_CLOUD_CHK_SUM);
147         cloudp = (nt_cloud_tp)handle;
148         assert(cloudp->usr_id);
149         assert(cloudp->passwd);
150         if(cloudp->query_url)
151                 free(cloudp->query_url);
152         if(cloudp->home_url)
153                 free(cloudp->home_url);
154         if(cloudp->token)
155                 free(cloudp->token);
156         cloudp->query_url = NULL;
157         cloudp->home_url = NULL;
158         cloudp->token = NULL;
159         
160         sprintf(post_data, "user=%s&passwd=%s", 
161                 cloudp->usr_id, cloudp->passwd);
162         
163         if(!nt_http_post(cloudp->auth_url, post_data,
164                         buf, sizeof(buf), NULL, NULL, NULL, NULL)){
165                 return FALSE;
166         }
167         linkp = nt_split_line(buf);
168         if(!linkp)
169                 return FALSE;
170         idx = 0;
171         wrkp = linkp;
172         do{
173                 switch(idx){
174                 case 0:
175                         cloudp->error_no = atoi((const char*)wrkp->data);
176                         if(100 != cloudp->error_no)
177                                 goto ERROR_TRAP;
178                         break;
179                 case 2:
180                         cloudp->query_url = nt_str_clone((const char*)wrkp->data);
181                         if(!cloudp->query_url)
182                                 goto ERROR_TRAP;
183                         break;
184                 case 3:
185                         cloudp->home_url = nt_str_clone((const char*)wrkp->data);
186                         if(!cloudp->query_url)
187                                 goto ERROR_TRAP;
188                         break;
189                 case 4:
190                         cloudp->token = nt_str_clone((const char*)wrkp->data);
191                         if(!cloudp->token)
192                                 goto ERROR_TRAP;
193                         break;
194                 }
195                 idx++;
196                 wrkp = wrkp->next;
197         }while(wrkp != linkp && idx < 5);
198         nt_all_link_free(linkp, NULL);
199         return TRUE;
200 ERROR_TRAP:
201         if(cloudp->query_url)
202                 free(cloudp->query_url);
203         if(cloudp->home_url)
204                 free(cloudp->home_url);
205         if(cloudp->token)
206                 free(cloudp->token);
207         cloudp->query_url = NULL;
208         cloudp->home_url = NULL;
209         cloudp->token = NULL;
210         if(linkp)
211                 nt_all_link_free(linkp, NULL);
212         return FALSE;
213 }
214
215 BOOL nt_cloud_insert_lines_into_file(nt_cloud_handle handle,
216                 const char *file_name, nt_link_tp lines)
217 {
218         return nt_cloud_edit_lines_file(handle, file_name, lines, "nc_insert_lines_file.php", 0);
219 }
220 BOOL nt_cloud_delete_lines_from_file(nt_cloud_handle handle,
221                 const char *file_name, nt_link_tp lines)
222 {
223         return nt_cloud_edit_lines_file(handle, file_name, lines, "nc_delete_lines_file.php", 0);
224 }
225
226 static BOOL nt_cloud_edit_lines_file(nt_cloud_handle handle,
227                 const char *file_name, nt_link_tp lines, const char *php_file, int depth)
228 {
229         char *url;
230         char buf1[1024*4];
231         char buf2[1024];
232         char *post_data;
233         static const int buf_delta = 2048*2;
234         nt_cloud_tp cloudp;
235         nt_link_tp linkp;
236         int len, num, idx;
237         nt_crypt_handle h_crypt;
238         iconv_t icd;
239         int result_code;
240         
241         assert(lines);
242         assert(handle);
243         assert(handle->chk_sum == NT_CLOUD_CHK_SUM);
244         cloudp = (nt_cloud_tp)handle;
245         assert(cloudp->usr_id);
246         assert(cloudp->token);
247         
248         num = nt_link_num(lines);
249         if(num <= 0)
250                 return FALSE;
251         len = strlen(cloudp->query_url);
252         len += strlen(php_file);
253         url = malloc(len+1);
254         if(!url)
255                 return FALSE;
256         strcpy(url, cloudp->query_url);
257         strcat(url, php_file);
258         
259         post_data = malloc(buf_delta);
260         if(!post_data){
261                 free(url);
262                 return FALSE;
263         }
264         
265         h_crypt = nt_crypt_get_handle();
266         if(!h_crypt){
267                 free(url);
268                 free(post_data);
269                 return FALSE;
270         }
271         icd =   iconv_open("cp932", "wchar_t");
272         if(((iconv_t)-1) == icd){
273                 nt_crypt_release_ref(h_crypt);
274                 free(url);
275                 free(post_data);
276                 return FALSE;
277         }
278         sprintf(post_data, "user=%s&token=%s&file_name=%s&num=%d", 
279                 cloudp->usr_id, cloudp->token, file_name, num);
280         linkp = lines;
281         idx = 1;
282         do{
283                 assert(idx <= num);
284                 if(nt_conv_wc2sjis(icd, (const wchar_t*)linkp->data,
285                                         buf1, sizeof(buf1))){
286                         len = nt_crypt_encrypt(h_crypt,
287                                                 (const unsigned char*)buf1,strlen(buf1),
288                                                 (unsigned char*)buf2, sizeof(buf2));
289                         if(len != -1){
290                                 if(nt_base64_url_encode((const unsigned char*)buf2,
291                                                 len, buf1, sizeof(buf1))){
292                                         snprintf(buf2, sizeof(buf2), "&n%d=", idx++);
293                                         strcat(post_data, buf2);
294                                         strcat(post_data, buf1);
295                                 }
296                         }
297                 }
298                 linkp = linkp->next;
299         }while(linkp != lines);
300         
301         iconv_close(icd);
302         nt_crypt_release_ref(h_crypt);
303         
304         if(!nt_http_post2(url, post_data,
305                         buf1, sizeof(buf1), NULL, NULL, NULL, NULL)){
306                 free(post_data);
307                 free(url);
308                 return FALSE;
309         }
310
311         result_code = nt_get_cloud_result(buf1);
312         free(post_data);
313         free(url);
314         if(result_code == 301 && depth == 0){
315                 if(!nt_cloud_chk_user(handle))
316                         return FALSE;
317                 return nt_cloud_edit_lines_file(handle,
318                                         file_name, lines, php_file, ++depth);
319         }else if(result_code != 100){
320                 return FALSE;
321         }
322         return TRUE;
323 }
324
325
326 nt_link_tp nt_cloud_download_file(nt_cloud_handle handle,
327                 const char *file_name)
328 {
329         char    *outp;
330         char    *url;
331         nt_cloud_tp cloudp;
332         nt_link_tp linkp, wrkp;
333         char buf1[1024];
334         char buf2[1024];
335         wchar_t wc[1024];
336         wchar_t *wcptr;
337         FILE    *fp_src;
338         char *cptr;
339         int len;
340         nt_crypt_handle h_crypt;
341         iconv_t icd = 0;
342         
343         
344         assert(handle);
345         assert(handle->chk_sum == NT_CLOUD_CHK_SUM);
346         cloudp = (nt_cloud_tp)handle;
347         assert(cloudp->home_url);
348         
349         len = strlen(cloudp->home_url);
350         len += strlen(file_name);
351         url = malloc(len+1);
352         if(!url)
353                 return FALSE;
354         strcpy(url, cloudp->home_url);
355         strcat(url, file_name);
356         
357         if(!nt_make_sha1_path(LOG_PATH, url, &outp)){
358                 free(url);
359                 return  FALSE;
360         }
361         
362         if(!nt_http_get(url, outp, NULL, NULL, NULL, FALSE, FALSE)){
363                 free(url);
364                 free(outp);
365                 return FALSE;
366         }
367         
368         fp_src  =       fopen(outp, "r");
369         if(!fp_src){
370                 free(url);
371                 free(outp);
372                 return FALSE;
373         }
374         
375         h_crypt = nt_crypt_get_handle();
376         if(!h_crypt){
377                 fclose(fp_src);
378                 free(url);
379                 free(outp);
380                 return FALSE;
381         }
382         
383         icd =   iconv_open("wchar_t", "cp932");
384         if(((iconv_t)-1) == icd){
385                 fclose(fp_src);
386                 free(url);
387                 free(outp);
388                 return FALSE;
389         }
390         
391         linkp = NULL;
392         while(1){
393                 if(feof(fp_src))
394                         break;
395                 if(!fgets(buf1, sizeof(buf1), fp_src))
396                         break;
397                 cptr = nt_trim2(buf1, buf2, sizeof(buf2));
398                 if(!cptr || *cptr == '\0')
399                         break;
400                 len = nt_base64_url_decode(cptr, strlen(cptr),
401                                         (unsigned char*)buf1, sizeof(buf1));
402                 if(len == -1)
403                         continue;
404                 len = nt_crypt_decrypt(h_crypt,
405                                         (const unsigned char*)buf1, len, 
406                                         (unsigned char*)buf2, sizeof(buf2));
407                 if(len == -1)
408                         continue;
409                 buf2[len] = '\0';
410                 if(!nt_conv_sjis2wc(icd, (const char*)buf2,
411                                         wc, sizeof(wc))){
412                         continue;
413                 }
414                 wcptr = nt_w_str_clone(wc);
415                 if(!wcptr)
416                         break;
417                 wrkp = nt_link_add_data(linkp, wcptr);
418                 if(!wrkp){
419                         free(wcptr);
420                         break;
421                 }
422                 if(!linkp)
423                         linkp = wrkp;
424         }
425         iconv_close(icd);
426         nt_crypt_release_ref(h_crypt);
427         fclose(fp_src);
428         free(url);
429         free(outp);
430         return linkp;
431 }
432
433 BOOL nt_cloud_upload_file(nt_cloud_handle handle,
434                 const char *file_name, nt_link_tp lines)
435 {
436         return nt_cloud_upload_file_local(handle,
437                         file_name, lines, 0);
438 }
439
440 static BOOL nt_cloud_upload_file_local(nt_cloud_handle handle,
441                 const char *file_name, nt_link_tp lines, int depth)
442 {
443         char *url;
444         char buf1[1024];
445         char buf2[1024];
446         char *post_data;
447         static const int buf_delta = 2048*2;
448         nt_cloud_tp cloudp;
449         nt_link_tp linkp;
450         int len;
451         nt_crypt_handle h_crypt;
452         iconv_t icd;
453         int result_code;
454         
455         assert(handle);
456         assert(handle->chk_sum == NT_CLOUD_CHK_SUM);
457         cloudp = (nt_cloud_tp)handle;
458         assert(cloudp->usr_id);
459         assert(cloudp->token);
460         
461         len = strlen(cloudp->query_url);
462         len += strlen("nc_write_file.php");
463         url = malloc(len+1);
464         if(!url)
465                 return FALSE;
466         strcpy(url, cloudp->query_url);
467         strcat(url, "nc_write_file.php");
468         
469         post_data = malloc(buf_delta);
470         if(!post_data){
471                 free(url);
472                 return FALSE;
473         }
474         
475         h_crypt = nt_crypt_get_handle();
476         if(!h_crypt){
477                 free(url);
478                 free(post_data);
479                 return FALSE;
480         }
481         icd =   iconv_open("cp932", "wchar_t");
482         if(((iconv_t)-1) == icd){
483                 nt_crypt_release_ref(h_crypt);
484                 free(url);
485                 free(post_data);
486                 return FALSE;
487         }
488         sprintf(post_data, "user=%s&token=%s&file_name=%s&data=", 
489                 cloudp->usr_id, cloudp->token, file_name);
490         linkp = lines;
491         do{
492                 if(nt_conv_wc2sjis(icd, (const wchar_t*)linkp->data,
493                                         buf1, sizeof(buf1))){
494                         len = nt_crypt_encrypt(h_crypt,
495                                                 (const unsigned char*)buf1,strlen(buf1),
496                                                 (unsigned char*)buf2, sizeof(buf2));
497                         if(len != -1){
498                                 if(nt_base64_url_encode((const unsigned char*)buf2,
499                                                 len, buf1, sizeof(buf1))){
500                                         strcat(post_data, buf1);
501                                         strcat(post_data, "\n");
502                                 }
503                         }
504                 }
505                 linkp = linkp->next;
506         }while(linkp != lines);
507         
508         iconv_close(icd);
509         nt_crypt_release_ref(h_crypt);
510         
511         if(!nt_http_post(url, post_data,
512                         buf1, sizeof(buf1), NULL, NULL, NULL, NULL)){
513                 free(post_data);
514                 free(url);
515                 return FALSE;
516         }
517         
518         result_code = nt_get_cloud_result(buf1);
519         if(result_code == 301 && depth == 0){
520                 if(!nt_cloud_chk_user(handle))
521                         return FALSE;
522                 return nt_cloud_upload_file_local(handle,
523                                         file_name, lines, ++depth);
524         }else if(result_code != 100){
525                 free(post_data);
526                 free(url);
527                 return FALSE;
528         }
529         return TRUE;
530 }
531
532 static int nt_get_cloud_result(const char *ptr)
533 {
534         int num;
535         
536         if(!ptr)
537                 return -1;
538         if(*ptr < '0' || *ptr > '9')
539                 return -1;
540         num = *ptr - '0';
541         ptr++;
542         while(*ptr){
543                 if(*ptr >= '0' && *ptr <= '9'){
544                         num *= 10;
545                         num += *ptr - '0';
546                         ptr++;
547                 }else{
548                         break;
549                 }
550         }
551         return num;
552 }
553
554 static nt_link_tp nt_split_line(char *data)
555 {
556         nt_link_tp linkp, wrkp;
557         char *cptr, *p;
558         
559         assert(data);
560         
561         linkp = NULL;
562         cptr = data;
563         do{
564                 wrkp = nt_link_add_data(linkp, cptr);
565                 if(!wrkp)
566                         goto ERROR_TRAP;
567                 if(!linkp)
568                         linkp = wrkp;
569                 p = strchr(cptr, '\n');
570                 if(p){
571                         *p = '\0';
572                         p++;
573                 }
574                 cptr = p;
575         }while(cptr);
576         
577         return linkp;
578 ERROR_TRAP:
579         if(linkp)
580                 nt_all_link_free(linkp, NULL);
581         return NULL;
582 }
583
584
585