implement adding friends
This commit is contained in:
		
							parent
							
								
									2e563b724a
								
							
						
					
					
						commit
						efce6a6543
					
				| @ -8,8 +8,19 @@ | |||||||
| struct dc_account_; | struct dc_account_; | ||||||
| typedef struct dc_account_ *dc_account_t; | typedef struct dc_account_ *dc_account_t; | ||||||
| 
 | 
 | ||||||
|  | typedef enum { | ||||||
|  |     FRIEND_STATE_NONE = 0, | ||||||
|  |     /* accountt is a mutual friend
 | ||||||
|  |      */ | ||||||
|  |     FRIEND_STATE_FRIEND = 1, | ||||||
|  |     /* pending account, the other side hasn't accepted yet
 | ||||||
|  |      */ | ||||||
|  |     FRIEND_STATE_PENDING = 4, | ||||||
|  | } dc_account_friend_states; | ||||||
|  | 
 | ||||||
| dc_account_t dc_account_new(void); | dc_account_t dc_account_new(void); | ||||||
| dc_account_t dc_account_new2(char const *email, char const *pass); | dc_account_t dc_account_new2(char const *email, char const *pass); | ||||||
|  | dc_account_t dc_account_from_fullid(char const *fullid); | ||||||
| 
 | 
 | ||||||
| void dc_account_set_email(dc_account_t a, char const *email); | void dc_account_set_email(dc_account_t a, char const *email); | ||||||
| char const *dc_account_email(dc_account_t a); | char const *dc_account_email(dc_account_t a); | ||||||
| @ -37,5 +48,7 @@ bool dc_account_has_token(dc_account_t a); | |||||||
| void dc_account_set_friends(dc_account_t a, dc_account_t *ptr, size_t len); | void dc_account_set_friends(dc_account_t a, dc_account_t *ptr, size_t len); | ||||||
| dc_account_t dc_account_nthfriend(dc_account_t a, size_t i); | dc_account_t dc_account_nthfriend(dc_account_t a, size_t i); | ||||||
| size_t dc_account_friends_size(dc_account_t a); | size_t dc_account_friends_size(dc_account_t a); | ||||||
|  | int dc_account_friend_state(dc_account_t a); | ||||||
|  | void dc_account_set_friend_state(dc_account_t a, int state); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -65,4 +65,9 @@ bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, | |||||||
|  */ |  */ | ||||||
| bool dc_api_get_friends(dc_api_t api, dc_account_t login); | bool dc_api_get_friends(dc_api_t api, dc_account_t login); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Add a given account as a friend to the friends list | ||||||
|  |  */ | ||||||
|  | bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -34,6 +34,9 @@ struct dc_account_ | |||||||
|     /* friends we have
 |     /* friends we have
 | ||||||
|      */ |      */ | ||||||
|     GPtrArray *friends; |     GPtrArray *friends; | ||||||
|  |     /* our own friend state
 | ||||||
|  |      */ | ||||||
|  |     int friend_state; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void dc_account_free(dc_account_t ptr) | static void dc_account_free(dc_account_t ptr) | ||||||
| @ -81,6 +84,38 @@ dc_account_t dc_account_new2(char const *email, char const *pass) | |||||||
|     return ptr; |     return ptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | dc_account_t dc_account_from_fullid(char const *fullid) | ||||||
|  | { | ||||||
|  |     return_if_true(fullid == NULL, NULL); | ||||||
|  | 
 | ||||||
|  |     char *name = strdup(fullid), *discriminator = NULL; | ||||||
|  |     dc_account_t acc = NULL; | ||||||
|  | 
 | ||||||
|  |     return_if_true(name == NULL, NULL); | ||||||
|  | 
 | ||||||
|  |     discriminator = strchr(name, '#'); | ||||||
|  |     if (discriminator == NULL || *discriminator == '\0') { | ||||||
|  |         free(name); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     *discriminator = '\0'; | ||||||
|  |     ++discriminator; | ||||||
|  | 
 | ||||||
|  |     acc = dc_account_new(); | ||||||
|  |     if (acc == NULL) { | ||||||
|  |         free(name); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     dc_account_set_username(acc, name); | ||||||
|  |     dc_account_set_discriminator(acc, discriminator); | ||||||
|  | 
 | ||||||
|  |     free(name); | ||||||
|  | 
 | ||||||
|  |     return acc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void dc_account_set_email(dc_account_t a, char const *email) | void dc_account_set_email(dc_account_t a, char const *email) | ||||||
| { | { | ||||||
|     return_if_true(a == NULL,); |     return_if_true(a == NULL,); | ||||||
| @ -219,3 +254,15 @@ size_t dc_account_friends_size(dc_account_t a) | |||||||
|     return_if_true(a == NULL || a->friends == NULL, 0); |     return_if_true(a == NULL || a->friends == NULL, 0); | ||||||
|     return a->friends->len; |     return a->friends->len; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | int dc_account_friend_state(dc_account_t a) | ||||||
|  | { | ||||||
|  |     return_if_true(a == NULL, 0); | ||||||
|  |     return a->friend_state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dc_account_set_friend_state(dc_account_t a, int state) | ||||||
|  | { | ||||||
|  |     return_if_true(a == NULL,); | ||||||
|  |     a->friend_state = state; | ||||||
|  | } | ||||||
|  | |||||||
| @ -349,6 +349,29 @@ error: | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static json_t *dc_api_user_to_json(dc_account_t a) | ||||||
|  | { | ||||||
|  |     json_t *j = NULL; | ||||||
|  | 
 | ||||||
|  |     return_if_true(a == NULL, NULL); | ||||||
|  |     return_if_true(dc_account_username(a) == NULL || | ||||||
|  |                    dc_account_discriminator(a) == NULL, | ||||||
|  |                    NULL | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     j = json_object(); | ||||||
|  |     return_if_true(j == NULL, NULL); | ||||||
|  | 
 | ||||||
|  |     json_object_set_new(j, "username", | ||||||
|  |                         json_string(dc_account_username(a)) | ||||||
|  |         ); | ||||||
|  |     json_object_set_new(j, "discriminator", | ||||||
|  |                         json_string(dc_account_discriminator(a)) | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     return j; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool dc_api_get_userinfo(dc_api_t api, dc_account_t login, | bool dc_api_get_userinfo(dc_api_t api, dc_account_t login, | ||||||
|                          dc_account_t user) |                          dc_account_t user) | ||||||
| { | { | ||||||
| @ -420,6 +443,15 @@ bool dc_api_get_friends(dc_api_t api, dc_account_t login) | |||||||
|         if (a == NULL) { |         if (a == NULL) { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         /* read the type also known as "typ"
 | ||||||
|  |          */ | ||||||
|  |         val = json_object_get(c, "type"); | ||||||
|  |         if (val != NULL && json_is_integer(val)) { | ||||||
|  |             int state = json_integer_value(val); | ||||||
|  |             dc_account_set_friend_state(a, state); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         g_ptr_array_add(f, a); |         g_ptr_array_add(f, a); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -440,6 +472,36 @@ cleanup: | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Add a given account as a friend to the friends list | ||||||
|  |  */ | ||||||
|  | bool dc_api_add_friend(dc_api_t api, dc_account_t login, dc_account_t friend) | ||||||
|  | { | ||||||
|  |     char const *url = "users/@me/relationships"; | ||||||
|  |     json_t *reply = NULL, *post = NULL; | ||||||
|  |     bool ret = false; | ||||||
|  | 
 | ||||||
|  |     return_if_true(api == NULL, false); | ||||||
|  |     return_if_true(login == NULL, false); | ||||||
|  | 
 | ||||||
|  |     post = dc_api_user_to_json(friend); | ||||||
|  |     return_if_true(post == NULL, false); | ||||||
|  | 
 | ||||||
|  |     reply = dc_api_call_sync(api, "POST", dc_account_token(login), url, post); | ||||||
|  |     /* apparently if no data comes back, then the whole thing was a success
 | ||||||
|  |      */ | ||||||
|  |     goto_if_true(reply != NULL, cleanup); | ||||||
|  | 
 | ||||||
|  |     ret = true; | ||||||
|  | 
 | ||||||
|  | cleanup: | ||||||
|  | 
 | ||||||
|  |     json_decref(post); | ||||||
|  |     json_decref(reply); | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, GPtrArray **out) | bool dc_api_get_userguilds(dc_api_t api, dc_account_t login, GPtrArray **out) | ||||||
| { | { | ||||||
|     char const *url = "users/@me/guilds"; |     char const *url = "users/@me/guilds"; | ||||||
|  | |||||||
| @ -1,9 +1,10 @@ | |||||||
| #include <ncdc/cmds.h> | #include <ncdc/cmds.h> | ||||||
| 
 | 
 | ||||||
| ncdc_commands_t cmds[] = { | ncdc_commands_t cmds[] = { | ||||||
|     { L"friends", ncdc_cmd_friends }, |     { L"/friend",  ncdc_cmd_friends }, | ||||||
|     { L"login", ncdc_cmd_login }, |     { L"/friends", ncdc_cmd_friends }, | ||||||
|     { L"quit", ncdc_cmd_quit }, |     { L"/login",   ncdc_cmd_login }, | ||||||
|  |     { L"/quit",    ncdc_cmd_quit }, | ||||||
|     { NULL, NULL } |     { NULL, NULL } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -36,7 +37,6 @@ static void *async_dispatcher(void *arg) | |||||||
|                 /* end of working orders
 |                 /* end of working orders
 | ||||||
|                  */ |                  */ | ||||||
|                 pthread_mutex_unlock(&mtx); |                 pthread_mutex_unlock(&mtx); | ||||||
|                 printf("got exit\n"); |  | ||||||
|                 return NULL; |                 return NULL; | ||||||
|             } else { |             } else { | ||||||
|                 /* call the handler
 |                 /* call the handler
 | ||||||
| @ -92,15 +92,17 @@ bool ncdc_dispatch_deinit(void) | |||||||
| bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s) | bool ncdc_dispatch(ncdc_mainwindow_t n, wchar_t const *s) | ||||||
| { | { | ||||||
|     wchar_t **tokens = NULL; |     wchar_t **tokens = NULL; | ||||||
|     size_t i = 0; |     size_t i = 0, tokenlen = 0; | ||||||
|     ncdc_commands_t *it = NULL; |     ncdc_commands_t *it = NULL; | ||||||
|     queue_item *item = NULL; |     queue_item *item = NULL; | ||||||
| 
 | 
 | ||||||
|     tokens = w_tokenise(s); |     tokens = w_tokenise(s); | ||||||
|     return_if_true(tokens == NULL, false); |     return_if_true(tokens == NULL, false); | ||||||
| 
 | 
 | ||||||
|  |     tokenlen = wcslen(tokens[0]); | ||||||
|  | 
 | ||||||
|     for (i = 0; cmds[i].name != NULL; i++) { |     for (i = 0; cmds[i].name != NULL; i++) { | ||||||
|         if (wcscmp(cmds[i].name, tokens[0]) == 0) { |         if (wcsncmp(cmds[i].name, tokens[0], tokenlen) == 0) { | ||||||
|             it = cmds+i; |             it = cmds+i; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | |||||||
| { | { | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|     size_t i = 0; |     size_t i = 0; | ||||||
|  |     wchar_t c = ' '; | ||||||
| 
 | 
 | ||||||
|     ret = dc_api_get_friends(api, current_account); |     ret = dc_api_get_friends(api, current_account); | ||||||
|     if (!ret) { |     if (!ret) { | ||||||
| @ -16,27 +17,67 @@ ncdc_cmd_friends_list(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | |||||||
|     LOG(n, L"/FRIENDS list"); |     LOG(n, L"/FRIENDS list"); | ||||||
|     for (i = 0; i < dc_account_friends_size(current_account); i++) { |     for (i = 0; i < dc_account_friends_size(current_account); i++) { | ||||||
|         dc_account_t acc = dc_account_nthfriend(current_account, i); |         dc_account_t acc = dc_account_nthfriend(current_account, i); | ||||||
|         LOG(n, L"  %s", dc_account_full_username(acc)); |         switch (dc_account_friend_state(acc)) { | ||||||
|  |         case FRIEND_STATE_PENDING: c = 'P'; break; | ||||||
|  |         default: c = ' '; break; | ||||||
|  |         } | ||||||
|  |         LOG(n, L"%lc %s", c, dc_account_full_username(acc)); | ||||||
|     } |     } | ||||||
|     LOG(n, L"End of /FRIENDS list"); |     LOG(n, L"End of /FRIENDS list"); | ||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | static bool | ||||||
|  | ncdc_cmd_friends_add(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | ||||||
| { | { | ||||||
|     wchar_t *subcmd = NULL; |     char *name = NULL; | ||||||
|  |     dc_account_t friend = NULL; | ||||||
|  |     bool ret = false; | ||||||
| 
 | 
 | ||||||
|     if (ac <= 1) { |     if (ac <= 1) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     name = w_convert(av[1]); | ||||||
|  |     return_if_true(name == NULL, false); | ||||||
|  | 
 | ||||||
|  |     friend = dc_account_from_fullid(name); | ||||||
|  |     if (friend == NULL) { | ||||||
|  |         LOG(n, L"friends: add: invalid username given, use the full ID"); | ||||||
|  |         goto cleanup; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!dc_api_add_friend(api, current_account, friend)) { | ||||||
|  |         LOG(n, L"friends: add: failed to add friend, Vulkan would be sad"); | ||||||
|  |         goto cleanup; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     LOG(n, L"friends: add: request for friendship sent"); | ||||||
|  |     ret = true; | ||||||
|  | 
 | ||||||
|  | cleanup: | ||||||
|  | 
 | ||||||
|  |     dc_unref(friend); | ||||||
|  |     free(name); | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | ||||||
|  | { | ||||||
|  |     wchar_t *subcmd = NULL; | ||||||
|  | 
 | ||||||
|     if (current_account == NULL || |     if (current_account == NULL || | ||||||
|         !dc_account_has_token(current_account)) { |         !dc_account_has_token(current_account)) { | ||||||
|         LOG(n, L"friends: not logged in"); |         LOG(n, L"friends: not logged in"); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (ac <= 1) { | ||||||
|  |         return ncdc_cmd_friends_list(n, ac, av); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     subcmd = av[1]; |     subcmd = av[1]; | ||||||
| 
 | 
 | ||||||
|     --ac; |     --ac; | ||||||
| @ -44,6 +85,8 @@ bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av) | |||||||
| 
 | 
 | ||||||
|     if (wcscmp(subcmd, L"list") == 0) { |     if (wcscmp(subcmd, L"list") == 0) { | ||||||
|         return ncdc_cmd_friends_list(n, ac, av); |         return ncdc_cmd_friends_list(n, ac, av); | ||||||
|  |     } else if (wcscmp(subcmd, L"add") == 0) { | ||||||
|  |         return ncdc_cmd_friends_add(n, ac, av); | ||||||
|     } else { |     } else { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -99,12 +99,12 @@ ncdc_mainwindow_callback(ncdc_input_t i, wchar_t const *s, | |||||||
| { | { | ||||||
|     ncdc_mainwindow_t mainwin = (ncdc_mainwindow_t)arg; |     ncdc_mainwindow_t mainwin = (ncdc_mainwindow_t)arg; | ||||||
| 
 | 
 | ||||||
|     if (s[0] == '/') { |     if (s != NULL && s[0] == '/') { | ||||||
|         if (s[1] == '\0') { |         if (s[1] == '\0') { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return ncdc_dispatch(mainwin, s+1); |         return ncdc_dispatch(mainwin, s); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return false; |     return false; | ||||||
|  | |||||||
							
								
								
									
										105
									
								
								ncdc/src/util.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								ncdc/src/util.c
									
									
									
									
									
								
							| @ -33,11 +33,11 @@ int aswprintf(wchar_t **buffer, wchar_t const *fmt, ...) | |||||||
|     return sz; |     return sz; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wchar_t* wcsndup(const wchar_t* string, size_t maxlen) | wchar_t* wcsndup(wchar_t const* string, size_t maxlen) | ||||||
| { | { | ||||||
|     size_t n = wcsnlen(string, maxlen) + 1; |     wchar_t* r = calloc(maxlen+1, sizeof(wchar_t)); | ||||||
|     wchar_t* r = calloc(n, sizeof(wchar_t)); |     return_if_true(r == NULL, NULL); | ||||||
|     return r == NULL ? NULL : wmemcpy(r, string, n); |     return wmemcpy(r, string, maxlen); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| size_t w_strlenv(wchar_t **s) | size_t w_strlenv(wchar_t **s) | ||||||
| @ -61,28 +61,56 @@ void w_strfreev(wchar_t **s) | |||||||
|     free(s); |     free(s); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wchar_t **w_tokenise(wchar_t const *w) | wchar_t **w_tokenise(wchar_t const *str) | ||||||
| { | { | ||||||
|  |     wchar_t const *p = NULL, *start_of_word = NULL; | ||||||
|  |     wint_t c; | ||||||
|     GPtrArray *array = g_ptr_array_new(); |     GPtrArray *array = g_ptr_array_new(); | ||||||
|     wchar_t const *item = w; |     enum states { DULL, IN_WORD, IN_STRING } state = DULL; | ||||||
|     wchar_t *dup = NULL; |  | ||||||
|     size_t len = 0, origlen = 0; |  | ||||||
| 
 | 
 | ||||||
|     while ((dup = w_next_tok(item)) != NULL) { |     for (p = str; *p != '\0'; p++) { | ||||||
|         len = origlen = wcslen(dup); |         c = (wint_t) *p; | ||||||
|  |         switch (state) { | ||||||
|  |         case DULL: | ||||||
|  |         { | ||||||
|  |             if (iswspace(c)) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             if (c == '"') { | ||||||
|  |                 state = IN_STRING; | ||||||
|  |                 start_of_word = p + 1; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             state = IN_WORD; | ||||||
|  |             start_of_word = p; | ||||||
|  |         } continue; | ||||||
| 
 | 
 | ||||||
|         if (*dup == '"') { |         case IN_STRING: | ||||||
|             memmove(dup, dup+1, sizeof(wchar_t)*(len-1)); |         { | ||||||
|             --len; |             if (c == '"') { | ||||||
|  |                 size_t len = (p - 2 - start_of_word); | ||||||
|  |                 wchar_t *s = wcsndup(start_of_word, len); | ||||||
|  |                 g_ptr_array_add(array, s); | ||||||
|  |                 state = DULL; | ||||||
|  |             } | ||||||
|  |         } continue; | ||||||
|  | 
 | ||||||
|  |         case IN_WORD: | ||||||
|  |         { | ||||||
|  |             if (iswspace(c)) { | ||||||
|  |                 size_t len = (p - start_of_word); | ||||||
|  |                 wchar_t *s = wcsndup(start_of_word, len); | ||||||
|  |                 g_ptr_array_add(array, s); | ||||||
|  |                 state = DULL; | ||||||
|  |             } | ||||||
|  |         } continue; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         if (len > 0 && dup[len-1] == '"') { |     if (state != DULL) { | ||||||
|             dup[len-1] = '\0'; |         size_t len = (p - start_of_word); | ||||||
|             --len; |         wchar_t *s = wcsndup(start_of_word, len); | ||||||
|         } |         g_ptr_array_add(array, s); | ||||||
| 
 |  | ||||||
|         g_ptr_array_add(array, dup); |  | ||||||
|         item += origlen; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     g_ptr_array_add(array, NULL); |     g_ptr_array_add(array, NULL); | ||||||
| @ -103,40 +131,3 @@ char *w_convert(wchar_t const *w) | |||||||
|     wcstombs(ptr, w, sz); |     wcstombs(ptr, w, sz); | ||||||
|     return ptr; |     return ptr; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| wchar_t *w_next_tok(wchar_t const *w) |  | ||||||
| { |  | ||||||
|     bool quotes = false; |  | ||||||
|     wchar_t const *start = NULL; |  | ||||||
| 
 |  | ||||||
|     /* skip first white spaces if there are any
 |  | ||||||
|      */ |  | ||||||
|     for (; *w != '\0' && iswspace(*w); w++) |  | ||||||
|         ; |  | ||||||
| 
 |  | ||||||
|     if (*w == '\0') { |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     start = w; |  | ||||||
|     quotes = (*w == '"'); |  | ||||||
| 
 |  | ||||||
|     do { |  | ||||||
|         if (iswspace(*w) && !quotes) { |  | ||||||
|             --w; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (*w == '"' && *(w-1) != '\\' && quotes) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (*w == '\0') { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ++w; |  | ||||||
|     } while (1); |  | ||||||
| 
 |  | ||||||
|     return wcsndup(start, (w - start)); |  | ||||||
| } |  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user