implement Flickr;
include "sys.m";
sys: Sys;
include "draw.m";
draw : Draw;
include "keyring.m";
keyring: Keyring;
include "/usr/maht/http_client/http_client.m";
http_client : Http_client;
Request, Connection, Response : import http_client;
include "/usr/maht/xmhell/xml.m";
xml: Xml;
Parser, Item, Attributes, Mark: import xml;
include "/usr/maht/mime/mime.m";
mime : Mime;
Document, Disposition : import mime;
include "bufio.m";
bufio : Bufio;
Iobuf : import bufio;
include "Flickr.m";
debug(b : array of byte)
{
t := array of byte sys->sprint("%s\n", string b);
sys->write(sys->fildes(2), t, len(t));
}
query_string(a: ref Auth, method: string, parameters : list of ref Parameter) : string
{
p : ref Parameter;
query_string := "";
if(a != nil) {
if (a.token != "")
query_string += "auth_token=" + a.token + "&";
query_string += "api_key=" + a.apikey + "&";
}
query_string += "method=flickr." + method;
for(ps:=parameters; ps != nil; ps = tl ps) {
p = hd ps;
query_string += "&" + http_client->urlencode(p.name) + "=" + http_client->urlencode(p.value) ;
}
return query_string;
}
sign_parameters(a: ref Auth, method : string, parameters : list of ref Parameter) : string
{
keyring = load Keyring Keyring->PATH;
sys = load Sys Sys->PATH;
digest := array[16] of byte;
p : ref Parameter;
unhashed := a.secret;
if (a != nil) {
unhashed += "api_key" + a.apikey;
if(a.token != "")
unhashed += "auth_token" + a.token;
}
if(method != "")
unhashed += "methodflickr." + method;
for(ps:=parameters; ps != nil; ps = tl ps) {
p = hd ps;
unhashed += p.name + p.value;
}
sys->print("unhashed: %s\n", unhashed);
keyring->md5(array of byte unhashed, len array of byte unhashed, digest, nil);
digest_text := "";
for(i:=0; i<16; i++) {
digest_text += sys->sprint("%02x", int(digest[i]));
}
return digest_text;
}
send_request(a: ref Auth, method : string, parameters : list of ref Parameter) : ref Response
{
http_client = load Http_client Http_client->PATH;
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
c := http_client->new_connection("tcp!" + IP + "!80");
b := bufio->fopen(c.c.dfd, Bufio->OWRITE);
bb := bufio->fopen(sys->fildes(1), Bufio->OWRITE);
body := array of byte (query_string(a, method, parameters) + "&api_sig=" + sign_parameters(a, method, parameters));
http_client->POST(b, Host, RESTForm, "1.1", "Content-Type: application/x-www-form-urlencoded" :: nil, body);
http_client->POST(bb, Host, RESTForm, "1.1", "Content-Type: application/x-www-form-urlencoded" :: nil, body);
b.flush();
bb.flush();
return c.read_response();
}
read_rsp_node(response : ref Response) : string
{
if(response == nil)
return "";
xml = load Xml Xml->PATH;
xml->init();
x := xml->init_io(string response.body, nil, "");
for(n := x.next(); n != nil; n = x.next()) {
pick e := n {
Tag =>
case e.name {
"rsp" =>
if(e.attrs.get("stat") == "ok")
x.down();
break;
* =>
x.down();
f := x.next();
pick g := f {
Text =>
return g.ch;
}
}
}
}
return "";
}
Auth.get_frob(a : self ref Auth) : string
{
response := send_request(a, "auth.getFrob", nil);
if(response == nil)
return "";
return read_rsp_node(response);
}
Auth.get_token(a: self ref Auth) : string
{
params := ref Parameter("frob", a.get_frob()) :: nil;
response := send_request(a, "auth.getToken", params);
return "";
}
Auth.check_token(a: self ref Auth) : int
{
response := send_request(a, "auth.checkToken", nil);
# sys->print("%s", response.to_string());
return 1;
}
Photo.to_string(p : self ref Photo) : string
{
return sys->sprint("Photo id=%s\n\towner: %s\n\tsecret: %s\n\tserver: %s\n\tfarm: %s\n\ttitle: %s\n\tispublic: %d\n\tisfriend: %d\n\tisfamily: %d\n", p.id, p.owner, p.secret, p.server, p.farm, p.title, p.ispublic, p.isfriend, p.isfamily);
}
response_to_photopage(response : ref Response) : ref Photopage
{
if(response == nil) return nil;
photopage := ref Photopage;
p : ref Photo;
xml = load Xml Xml->PATH;
xml->init();
x := xml->init_io(string response.body, nil, "");
for(n := x.next(); n != nil; n = x.next()) {
pick e := n {
Tag =>
case e.name {
"rsp" =>
if(e.attrs.get("stat") == "ok")
x.down();
break;
"photos" =>
photopage.page = int e.attrs.get("page");
photopage.pages = int e.attrs.get("pages");
photopage.perpage = int e.attrs.get("perpage");
photopage.total = int e.attrs.get("total");
x.down();
"photo" =>
p = ref Photo;
p.id = e.attrs.get("id");
p.owner = e.attrs.get("owner");
p.secret = e.attrs.get("secret");
p.server = e.attrs.get("server");
p.farm = e.attrs.get("farm");
p.title = e.attrs.get("title");
p.ispublic = int e.attrs.get("ispublic");
p.isfriend = int e.attrs.get("isfriend");
p.isfamily = int e.attrs.get("isfamily");
photopage.photos = p :: photopage.photos;
}
}
}
return photopage;
}
get_favourites(a : ref Auth, per_page, page_no : int) : ref Photopage
{
params := ref Parameter("page", sys->sprint("%d", page_no)) ::ref Parameter("per_page", sys->sprint("%d", per_page)) :: nil;
return response_to_photopage(send_request(a, "favorites.getList", params));
}
upload_jpeg(a: ref Auth, jpeg : array of byte) : string
{
mime = load Mime Mime->PATH;
d := mime->new_document();
d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "photo") :: ref mime->Keyval("filename", "hail_glenda.jpeg") :: nil), "image/jpeg", jpeg);
sig := sign_parameters(a, "", nil);
# d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "is_public") :: nil), "", array of byte "1");
# d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "tags") :: nil), "", array of byte "tag1 tag2 tag3");
# d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "description") :: nil), "", array of byte "This is the description");
# d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "title") :: nil), "", array of byte "This is the title");
d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "api_sig") :: nil), "", array of byte sig);
d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "auth_token") :: nil), "", array of byte a.token);
d.add_part(ref Disposition("form-data", ref mime->Keyval("name", "api_key") :: nil), "", array of byte a.apikey);
http_client = load Http_client Http_client->PATH;
sys = load Sys Sys->PATH;
c := http_client->new_connection("tcp!" + IP + "!80");
b := bufio->fopen(c.c.dfd, Bufio->OWRITE);
http_client->POST(b, Host, UploadForm, "1.1", "Content-type: multipart/form-data; boundary=" + d.boundary :: "Accept-Encoding: identity" :: nil, d.bytes());
b.flush();
return read_rsp_node(c.read_response());
}
Category.to_string(c : self ref Category) : string
{
return sys->sprint("C:%s\n\tid: %d\n\tp:%d\n\tc: %d", c.name, c.id, c.parent, c.count);
}
Group.to_string(g : self ref Group) : string
{
return sys->sprint("G:%s\n\tnsid: %s\n\tmembers: %d", http_client->urlencode(g.name), g.nsid, g.members);
}
groups_browse(a: ref Auth, category_id : int) : (list of ref Category, list of ref Group)
{
params := ref Parameter("cat_id", sys->sprint("%d", category_id)) :: nil;
response := send_request(a, "groups.browse", params);
if(response == nil)
return (nil, nil);
categories : list of ref Category;
groups : list of ref Group;
g := ref Group;
c : ref Category;
xml = load Xml Xml->PATH;
xml->init();
p := xml->init_io(string response.body, nil, "");
for(i := p.next(); i != nil; i = p.next()) {
pick e := i {
Tag =>
case e.name {
"rsp" =>
if(e.attrs.get("stat") == "ok")
p.down();
break;
"category" =>
p.down();
"subcat" =>
c = ref Category;
c.id = int e.attrs.get("id");
c.parent = int category_id;
c.name = e.attrs.get("name");
c.count = int e.attrs.get("count");
categories = c :: categories;
"group" =>
g = ref Group;
g.nsid =e.attrs.get("nsid");
g.name = e.attrs.get("name");
g.members = int e.attrs.get("members");
groups = g :: groups;
}
}
}
return (categories, groups);
}
my_recently_posted_photos(a: ref Auth, per_page, page_no : int) : ref Photopage
{
params := ref Parameter("page", sys->sprint("%d", page_no)) ::ref Parameter("per_page", sys->sprint("%d", per_page)) :: ref Parameter("user_id", "me") :: nil;;
return response_to_photopage(send_request(a, "photos.search", params));
}
Photopage.to_string(photopage: self ref Photopage) : string
{
page := sys->sprint("Page %d of %d x%d = %d\n", photopage.page, photopage.pages, photopage.perpage, photopage.total);
p : ref Photo;
for(ps := photopage.photos; ps != nil; ps = tl ps) {
p = hd ps;
page += "\t" + p.to_string() + "\n";
}
return page;
}
# Put Limbo Flickr
|