Skip to content
This repository has been archived by the owner on Nov 18, 2023. It is now read-only.

Commit

Permalink
Splitting objects.
Browse files Browse the repository at this point in the history
  • Loading branch information
residuum committed Sep 25, 2012
1 parent c0c9cda commit 2cee983
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 225 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -6,11 +6,11 @@ LIBRARY_NAME = purest_json
# add your .c source files, one object per file, to the SOURCES
# variable, help files will be included automatically, and for GUI
# objects, the matching .tcl file too
SOURCES = rest-json.c json-decode.c json-encode.c urlparams.c
SOURCES = rest.c oauth.c json-decode.c json-encode.c urlparams.c

# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
# be included automatically
PDOBJECTS =
PDOBJECTS = rest-json.pd

# example patches and related files, in the 'examples' subfolder
EXAMPLES = purest-json-test.pd the-sound-of-money.pd twitter-visualization.pd statistics.pd
Expand Down
10 changes: 8 additions & 2 deletions README.txt
Expand Up @@ -29,8 +29,11 @@ package very much a community effort.

Externals in the library

[rest-json]
Object for issuing HTTP request. Received data is parsed as JSON data.
[rest]
Object for issuing HTTP request.

[oauth]
Object for issuing GET and POST requests with OAUTH.

[json-encode]
Object for encoding data to JSON.
Expand All @@ -41,6 +44,9 @@ Object for decoding JSON data.
[urlparams]
Object for url encoding and contatenating url parameters.

[rest-json]
Object for issuing HTTP request. Received data is parsed as JSON data.

For the usage of the externals see the help patches for the objects.


Expand Down
2 changes: 1 addition & 1 deletion json-decode.c
Expand Up @@ -6,7 +6,7 @@

static t_class *json_decode_class;

void setup_json0x2ddecode(void) {
void json0x2ddecode_setup(void) {
json_decode_class = class_new(gensym("json-decode"), (t_newmethod)json_decode_new,
0, sizeof(t_json_decode), 0, A_GIMME, 0);
class_addsymbol(json_decode_class, (t_method)json_decode_string);
Expand Down
2 changes: 1 addition & 1 deletion json-encode.c
Expand Up @@ -40,7 +40,7 @@ static json_object *create_object(char *value) {
return object;
}

void setup_json0x2dencode(void) {
void json0x2dencode_setup(void) {
json_encode_class = class_new(gensym("json-encode"), (t_newmethod)json_encode_new,
(t_method)json_encode_free, sizeof(t_json_encode), 0, A_GIMME, 0);
class_addbang(json_encode_class, (t_method)json_encode_bang);
Expand Down
207 changes: 207 additions & 0 deletions oauth.c
@@ -0,0 +1,207 @@
/*
* [oauth] makes RESTful calls to webservices.
* */

#include "purest_json.h"

static t_class *oauth_class;

static void *execute_oauth_request(void *thread_args) {
t_oauth *x = (t_oauth *)thread_args;
char *req_url = NULL;
char *postargs = NULL;
char *reply = NULL;
t_atom http_status_data[3];

if (strcmp(x->request_type, "POST") == 0) {
if (x->parameters) {
if (strchr(x->complete_url, '?')) {
strcat(x->complete_url, "&");
} else {
strcat(x->complete_url, "?");
}
strcat(x->complete_url, x->parameters);
}
req_url = oauth_sign_url2(x->complete_url, &postargs, OA_HMAC, NULL,
x->oauth.client_key, x->oauth.client_secret,
x->oauth.token_key, x->oauth.token_secret);
reply = oauth_http_post(req_url, postargs);
} else {
req_url = oauth_sign_url2(x->complete_url, NULL, OA_HMAC, NULL,
x->oauth.client_key, x->oauth.client_secret,
x->oauth.token_key, x->oauth.token_secret);
reply = oauth_http_get(req_url, NULL);
}
SETSYMBOL(&http_status_data[0], gensym("oauth"));

if (!reply) {
SETSYMBOL(&http_status_data[1], gensym("no reply"));
error("Request did not return value");
} else {
SETSYMBOL(&http_status_data[1], gensym("bang"));
outlet_symbol(x->x_ob.ob_outlet, gensym(reply));
}
outlet_list(x->status_info_outlet, &s_list, 2, &http_status_data[0]);
if (postargs) {
free(postargs);
}
if (req_url) {
free(req_url);
}
if (reply) {
free(reply);
}
x->is_data_locked = 0;
return NULL;
}

static void thread_execute(t_oauth *x, void *(*func) (void *)) {
int rc;
pthread_t thread;
pthread_attr_t thread_attributes;

pthread_attr_init(&thread_attributes);
pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
rc = pthread_create(&thread, &thread_attributes, func, (void *)x);
pthread_attr_destroy(&thread_attributes);
if (rc) {
error("Could not create thread with code %d", rc);
x->is_data_locked = 0;
}
}

static void set_url_parameters(t_oauth *x, int argcount, t_atom *argvec) {
switch (argcount) {
case 3:
if (argvec[0].a_type != A_SYMBOL) {
error("Base URL cannot be set.");
} else {
atom_string(argvec, x->base_url, MAXPDSTRING);
}
if (argvec[1].a_type != A_SYMBOL) {
error("Client key cannot be set.");
} else {
atom_string(argvec + 1, x->oauth.client_key, MAXPDSTRING);
}
if (argvec[2].a_type != A_SYMBOL) {
error("Client secret cannot be set.");
} else {
atom_string(argvec + 2, x->oauth.client_secret, MAXPDSTRING);
}
memset(x->oauth.token_key, 0x00, MAXPDSTRING);
memset(x->oauth.token_secret, 0x00, MAXPDSTRING);
break;
case 5:
if (argvec[0].a_type != A_SYMBOL) {
error("Base URL cannot be set.");
} else {
atom_string(argvec, x->base_url, MAXPDSTRING);
}
if (argvec[1].a_type != A_SYMBOL) {
error("Client key cannot be set.");
} else {
atom_string(argvec + 1, x->oauth.client_key, MAXPDSTRING);
}
if (argvec[2].a_type != A_SYMBOL) {
error("Client secret cannot be set.");
} else {
atom_string(argvec + 2, x->oauth.client_secret, MAXPDSTRING);
}
if (argvec[3].a_type != A_SYMBOL) {
error("Token key cannot be set.");
} else {
atom_string(argvec + 3, x->oauth.token_key, MAXPDSTRING);
}
if (argvec[4].a_type != A_SYMBOL) {
error("Token secret cannot be set.");
} else {
atom_string(argvec + 4, x->oauth.token_secret, MAXPDSTRING);
}
break;
default:
error("Wrong number of parameters.");
break;
}
}

void oauth_setup(void) {
oauth_class = class_new(gensym("oauth"), (t_newmethod)oauth_new,
0, sizeof(t_oauth), 0, A_GIMME, 0);
class_addmethod(oauth_class, (t_method)oauth_url, gensym("url"), A_GIMME, 0);
class_addmethod(oauth_class, (t_method)oauth_command, gensym("GET"), A_GIMME, 0);
class_addmethod(oauth_class, (t_method)oauth_command, gensym("POST"), A_GIMME, 0);
}

void oauth_command(t_oauth *x, t_symbol *selector, int argcount, t_atom *argvec) {
char *request_type;
char path[MAXPDSTRING];
char parameters[MAXPDSTRING];
char *cleaned_parameters;
size_t memsize = 0;
t_atom auth_status_data[2];

if(x->is_data_locked) {
post("oauth object is performing request and locked");
} else {
memset(x->request_type, 0x00, 7);
memset(x->parameters, 0x00, MAXPDSTRING);
memset(x->complete_url, 0x00, MAXPDSTRING);
switch (argcount) {
case 0:
break;
default:
request_type = selector->s_name;
atom_string(argvec, path, MAXPDSTRING);
if (argcount > 1) {
atom_string(argvec + 1, parameters, MAXPDSTRING);
}
x->is_data_locked = 1;
if (x->base_url != NULL) {
strcpy(x->complete_url, x->base_url);
}
strcat(x->complete_url, path);
strcpy(x->request_type, request_type);
if (parameters != NULL) {
cleaned_parameters = remove_backslashes(parameters, memsize);
strcpy(x->parameters, cleaned_parameters);
freebytes(cleaned_parameters, memsize);
}
if ((strcmp(x->request_type, "GET") &&
strcmp(x->request_type, "POST"))) {
SETSYMBOL(&auth_status_data[0], gensym("oauth"));
SETSYMBOL(&auth_status_data[1], gensym("Request Method not supported"));
error("Request method %s not supported.", x->request_type);
outlet_list(x->status_info_outlet, &s_list, 2, &auth_status_data[0]);
x->is_data_locked = 0;
} else {
thread_execute(x, execute_oauth_request);
}
break;
}
}
}

void oauth_url(t_oauth *x, t_symbol *selector, int argcount, t_atom *argvec) {

(void) selector;

if(x->is_data_locked) {
post("oauth object is performing request and locked");
} else {
set_url_parameters(x, argcount, argvec);
}
}

void *oauth_new(t_symbol *selector, int argcount, t_atom *argvec) {
t_oauth *x = (t_oauth *)pd_new(oauth_class);

(void) selector;

set_url_parameters(x, argcount, argvec);

outlet_new(&x->x_ob, NULL);
x->status_info_outlet = outlet_new(&x->x_ob, NULL);
x->is_data_locked = 0;

return (void *)x;
}
7 changes: 4 additions & 3 deletions purest_json.c
Expand Up @@ -4,8 +4,9 @@ void purest_json_setup(void) {
post("PuREST JSON version %s: A library for executing HTTP queries and encoding and decoding JSON data from Puredata.", LIBRARY_VERSION);
post("(c) Thomas Mayer (Residuum) 2012");
post("Get the latest source from https://github.com/residuum/PuRestJson");
setup_rest0x2djson();
setup_json0x2dencode();
setup_json0x2ddecode();
rest_setup();
oauth_setup();
json0x2dencode_setup();
json0x2ddecode_setup();
urlparams_setup();
}
70 changes: 40 additions & 30 deletions purest_json.h
Expand Up @@ -10,11 +10,6 @@

#define LIBRARY_VERSION "0.7.1"

typedef enum {
COOKIE,
OAUTH
} AuthType;

/* reading / writing data in HTTP requests */
typedef struct memory_struct {
char *memory;
Expand All @@ -29,30 +24,18 @@ typedef struct key_value_pair {
struct key_value_pair *next;
} t_key_value_pair;

/* [rest-json] */
/* [rest] */
typedef struct rest {
t_object x_ob;
t_outlet *done_outlet;
t_outlet *status_info_outlet;
int out_count;
char base_url[MAXPDSTRING];
/* authentication: cookie / oauth */
AuthType auth_type;
union {
struct {
char login_path[MAXPDSTRING];
char username[MAXPDSTRING];
char password[MAXPDSTRING];
char auth_token[MAXPDSTRING];
} cookie;
struct {
char request_type[5]; /*GET or POST*/
char client_key[MAXPDSTRING];
char client_secret[MAXPDSTRING];
char token_key[MAXPDSTRING];
char token_secret[MAXPDSTRING];
} oauth;
} auth;
/* authentication: cookie */
struct {
char login_path[MAXPDSTRING];
char username[MAXPDSTRING];
char password[MAXPDSTRING];
char auth_token[MAXPDSTRING];
} cookie;
t_atom *out;
/* threading */
char request_type[7]; /*One of GET, PUT, POST; DELETE*/
Expand All @@ -62,6 +45,28 @@ typedef struct rest {
/* end threading */
} t_rest;

/* [oauth] */
typedef struct oauth {
t_object x_ob;
t_outlet *status_info_outlet;
char base_url[MAXPDSTRING];
/* authentication*/
struct {
char request_type[5]; /*GET or POST*/
char client_key[MAXPDSTRING];
char client_secret[MAXPDSTRING];
char token_key[MAXPDSTRING];
char token_secret[MAXPDSTRING];
} oauth;
t_atom *out;
/* threading */
char request_type[7]; /*One of GET, PUT, POST; DELETE*/
char parameters[MAXPDSTRING];
char complete_url[MAXPDSTRING];
short is_data_locked;
/* end threading */
} t_oauth;

/* [json-encode] */
typedef struct json_encode {
t_object x_ob;
Expand All @@ -84,16 +89,21 @@ typedef struct urlparams {
int data_count;
} t_urlparams;

/* [rest-json] */
void setup_rest0x2djson(void);
/* [rest] */
void rest_setup(void);
void *rest_new(t_symbol *selector, int argcount, t_atom *argvec);

void rest_command(t_rest *x, t_symbol *selector, int argcount, t_atom *argvec);
void rest_url(t_rest *x, t_symbol *selector, int argcount, t_atom *argvec);
void rest_oauth(t_rest *x, t_symbol *selector, int argcount, t_atom *argvec);

/* [oauth] */
void oauth_setup(void);
void *oauth_new(t_symbol *selector, int argcount, t_atom *argvec);

void oauth_command(t_oauth *x, t_symbol *selector, int argcount, t_atom *argvec);
void oauth_url(t_oauth *x, t_symbol *selector, int argcount, t_atom *argvec);
/* [json-encode] */
void setup_json0x2dencode(void);
void json0x2dencode_setup(void);
void *json_encode_new(t_symbol *selector, int argcount, t_atom *argvec);
void json_encode_free(t_json_encode *x, t_symbol *selector, int argcount, t_atom *argvec);

Expand All @@ -103,7 +113,7 @@ void json_encode_array_add(t_json_encode *x, t_symbol *selector, int argcount, t
void json_encode_clear(t_json_encode *x, t_symbol *selector, int argcount, t_atom *argvec);

/* [json-decode] */
void setup_json0x2ddecode(void);
void json0x2ddecode_setup(void);
void *json_decode_new(t_symbol *selector, int argcount, t_atom *argvec);

void json_decode_string(t_json_decode *x, t_symbol *data);
Expand Down

0 comments on commit 2cee983

Please sign in to comment.