1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
#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;
|