|  | #include <u.h> | 
|  | #include <errno.h> | 
|  | #include <libc.h> | 
|  | #include <fcall.h> | 
|  | #include <thread.h> | 
|  | #include <auth.h> | 
|  | #include <9p.h> | 
|  | #include <libsec.h> | 
|  |  | 
|  | #define APIKEY        "G9ANE2zvCozKEoLQ5qaR1AUtcE5YpuDj" | 
|  | #define HOST          "api.smugmug.com" | 
|  | #define UPLOAD_HOST   "upload.smugmug.com" | 
|  | #define API_VERSION   "1.2.1" | 
|  | #define PATH          "/services/api/json/" API_VERSION "/" | 
|  | #define USER_AGENT    "smugfs (part of Plan 9 from User Space)" | 
|  |  | 
|  | void*	emalloc(int); | 
|  | void*	erealloc(void*, int); | 
|  | char*	estrdup(char*); | 
|  | int	urlencodefmt(Fmt*); | 
|  | int	timefmt(Fmt*); | 
|  | int	writen(int, void*, int); | 
|  |  | 
|  |  | 
|  | // Generic cache | 
|  |  | 
|  | typedef struct Cache Cache; | 
|  | typedef struct CEntry CEntry; | 
|  |  | 
|  | struct CEntry | 
|  | { | 
|  | char *name; | 
|  | struct { | 
|  | CEntry *next; | 
|  | CEntry *prev; | 
|  | } list; | 
|  | struct { | 
|  | CEntry *next; | 
|  | } hash; | 
|  | }; | 
|  |  | 
|  | Cache *newcache(int sizeofentry, int maxentry, void (*cefree)(CEntry*)); | 
|  | CEntry *cachelookup(Cache*, char*, int); | 
|  | void cacheflush(Cache*, char*); | 
|  |  | 
|  | // JSON parser | 
|  |  | 
|  | typedef struct Json Json; | 
|  |  | 
|  | enum | 
|  | { | 
|  | Jstring, | 
|  | Jnumber, | 
|  | Jobject, | 
|  | Jarray, | 
|  | Jtrue, | 
|  | Jfalse, | 
|  | Jnull | 
|  | }; | 
|  |  | 
|  | struct Json | 
|  | { | 
|  | int ref; | 
|  | int type; | 
|  | char *string; | 
|  | double number; | 
|  | char **name; | 
|  | Json **value; | 
|  | int len; | 
|  | }; | 
|  |  | 
|  | void	jclose(Json*); | 
|  | Json*	jincref(Json*); | 
|  | vlong	jint(Json*); | 
|  | Json*	jlookup(Json*, char*); | 
|  | double	jnumber(Json*); | 
|  | int	jsonfmt(Fmt*); | 
|  | int	jstrcmp(Json*, char*); | 
|  | char*	jstring(Json*); | 
|  | Json*	jwalk(Json*, char*); | 
|  | Json*	parsejson(char*); | 
|  |  | 
|  |  | 
|  | // Wrapper to hide whether we're using OpenSSL for HTTPS. | 
|  |  | 
|  | typedef struct Protocol Protocol; | 
|  | typedef struct Pfd Pfd; | 
|  | struct Protocol | 
|  | { | 
|  | Pfd *(*connect)(char *host); | 
|  | int (*read)(Pfd*, void*, int); | 
|  | int (*write)(Pfd*, void*, int); | 
|  | void (*close)(Pfd*); | 
|  | }; | 
|  |  | 
|  | Protocol http; | 
|  | Protocol https; | 
|  |  | 
|  |  | 
|  | // HTTP library | 
|  |  | 
|  | typedef struct HTTPHeader HTTPHeader; | 
|  | struct HTTPHeader | 
|  | { | 
|  | int code; | 
|  | char proto[100]; | 
|  | char codedesc[100]; | 
|  | vlong contentlength; | 
|  | char contenttype[100]; | 
|  | }; | 
|  |  | 
|  | char *httpreq(Protocol *proto, char *host, char *request, HTTPHeader *hdr, int rfd, vlong rlength); | 
|  | int httptofile(Protocol *proto, char *host, char *req, HTTPHeader *hdr, int wfd); | 
|  |  | 
|  |  | 
|  | // URL downloader - caches in files on disk | 
|  |  | 
|  | int download(char *url, HTTPHeader *hdr); | 
|  | void downloadflush(char*); | 
|  |  | 
|  | // JSON RPC | 
|  |  | 
|  | enum | 
|  | { | 
|  | MaxResponse = 1<<29, | 
|  | }; | 
|  |  | 
|  | Json*	jsonrpc(Protocol *proto, char *host, char *path, char *method, char *name1, va_list arg, int usecache); | 
|  | Json*	jsonupload(Protocol *proto, char *host, char *req, int rfd, vlong rlength); | 
|  | void	jcacheflush(char*); | 
|  |  | 
|  | extern int chattyhttp; | 
|  |  | 
|  |  | 
|  | // SmugMug RPC | 
|  |  | 
|  | #ifdef __GNUC__ | 
|  | #define check_nil __attribute__((sentinel)) | 
|  | #else | 
|  | #define check_nil | 
|  | #endif | 
|  |  | 
|  | Json* smug(char *method, char *name1, ...) check_nil;  // cached, http | 
|  | Json* ncsmug(char *method, char *name1, ...) check_nil;  // not cached, https | 
|  |  | 
|  |  | 
|  | // Session information | 
|  |  | 
|  | extern Json *userinfo; | 
|  | extern char *sessid; | 
|  |  | 
|  |  | 
|  | // File system | 
|  |  | 
|  | extern Srv xsrv; | 
|  | void xinit(void); | 
|  | extern int nickindex(char*); | 
|  |  | 
|  | // Logging | 
|  |  | 
|  | typedef struct Logbuf Logbuf; | 
|  | struct Logbuf | 
|  | { | 
|  | Req *wait; | 
|  | Req **waitlast; | 
|  | int rp; | 
|  | int wp; | 
|  | char *msg[128]; | 
|  | }; | 
|  |  | 
|  | extern void	lbkick(Logbuf*); | 
|  | extern void	lbappend(Logbuf*, char*, ...); | 
|  | extern void	lbvappend(Logbuf*, char*, va_list); | 
|  | /* #pragma varargck argpos lbappend 2 */ | 
|  | extern void	lbread(Logbuf*, Req*); | 
|  | extern void	lbflush(Logbuf*, Req*); | 
|  | /* #pragma varargck argpos flog 1 */ | 
|  |  | 
|  | extern void	rpclog(char*, ...); | 
|  | extern void	rpclogflush(Req*); | 
|  | extern void	rpclogread(Req*); | 
|  | extern void	rpclogwrite(Req*); | 
|  |  | 
|  | enum | 
|  | { | 
|  | STACKSIZE = 32768 | 
|  | }; | 
|  |  | 
|  | extern int printerrors; | 
|  |  |