/ Published in: R
URL: http://rebol.wik.is/Googledocs
Expand |
Embed | Plain Text
rebol [ file: googledocs.r author: "Graham Chiu" rights: 'BSD date: 15-Aug-2009 notes: { authenticates using clientauth against googledocs, and upload an acceptable document. Returns an XML object with accessor functions } comment: { 16-Aug-2009 - get list of folders and resourceids } ] do %/c/rebol-sdk-276/source/prot-http.r ; enhanced http protocol do http://www.ross-gill.com/r/altxml.r ; Chris' XML parser - see http://www.ross-gill.com/page/XML+and+REBOL googledocs: make object! [ auth: none ; the authentication token - can store in db and restore it. folders: copy [] ; holds the list of folders set-auth: func [ token [string!] ][ self/auth: token ] authenticate: func [ email [email!] password [string!] client [string!] service [string!] /insecure { use http and not https } /local token page ][ page: read/custom join either insecure [ http:// ][https://] "www.google.com/accounts/ClientLogin" compose [ POST (rejoin [ "Email=" email "&Passwd=" password "&source=" client "&service=" service] ) ] either parse page [ to "Auth=" copy token to end ][ set-auth trim/tail token true ][ false ] ] create-doc+metadata: func [ docname [string!] /local template ][ rejoin [ {<?xml version='1.0' encoding='UTF-8'?> <atom:entry xmlns:atom="http://www.w3.org/2005/Atom"> <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#document" label="document"/> <atom:title>} docname {</atom:title> </atom:entry>}] ] upload-document: func [ docname [string!] source [file! string!] content-type [string!] /raw /local boundary filedata result payload ][ if none? self/auth [ return false ] ; or throw an error boundary: rejoin ["__REBOL__" system/version "__" checksum form now/precise "__"] filedata: either file? source [ read/binary source ][ source ] payload: to-string rejoin [ #{} "--" boundary newline "Content-Type: application/atom+xml" newline newline create-doc+metadata docname newline newline "--" boundary newline "Content-Type: " content-type newline newline filedata newline newline "--" boundary "--" newline newline] result: read/custom http://docs.google.com/feeds/documents/private/full compose/deep [ POST (payload) [ content-type: (rejoin [ "multipart/related; boundary=" boundary ]) Authorization: (join "GoogleLogin " self/auth) ] ] either raw [ result ][ load-xml/dom result ] ] read-resource: func [ resource [string!] /local url][ url: switch/default resource [ "folders" [ http://docs.google.com/feeds/documents/private/full/-/folder?showfolders=true ] ][ none ] either url [ read/custom url compose/deep [ GET "" [ content-type: "application/atom+xml" Authorization: (join "GoogleLogin " self/auth) ] ] ][ false ] ] get-list-of-folders: func [ /raw /local page xmlobject result title resourceb][ result: copy [] page: read-resource "folders" either all [ not raw page ] [ ; process page to retrieve resourceids and folder names and return as a block of [ name resourceids pairs ] xmlobject: load-xml/dom page ; gets a block of entries ; entries: xmlobject/get-by-tag <entry> foreach entry xmlobject/get-by-tag <entry> [ ; get the title first title: entry/get-by-tag <title> ; title is a block! but there should be only one member ; if the folder name is not present, add it if not find result name: select title/1/value /text [ repend result [ name copy [] ] ] ; now get the resourceid with this folder resourceb: entry/get-by-tag <resourceid> ; append the resourceid value to the block associated with this foldername - if we have duplicate folder names, we get a block of resourceids append select result name resourceb/1/value ] self/folders: copy/deep result result ][ page ] ] get-folder-resourceids: func [ foldername /local folders][ if empty? self/folders [ folders: get-list-of-folders ] select self/folders foldername ] ] halt ; create an instance of the googledocs object gdoc: make googledocs [] ; authenticate against the documents service named "writely" goggledocs/authenticate myname@gmail.com q@$$w0rb "rebolapp" "writely" ; upload a text document to root folder and return an xmlobject with accessor functions xmlobject: googledocs/upload-document "my document" %test.rtf "application/msword" ; upload a text document to root folder and return the raw XML xml: gdoc/upload-document/raw "my document" %test.rtf "application/msword" ; upload a binary document to root folder, and call it "my document" xml: googledocs/upload-document/raw "my document" %test.rtf "application/msword" ; get the resourceid for a folder id: gdoc/get-folder-resourceids "my folder" >>[{folder:0B6ELdnC15jkoOWRhNDJlMTgtYjhkOS00YTli............}]
Comments
Subscribe to comments
You need to login to post a comment.

POST /feeds/documents/private/full HTTP/1.0 Accept: / Connection: close User-Agent: REBOL View 2.7.6.3.1 Host: docs.google.com Referer: http://docs.google.com/feeds/documents/private/full Content-Type: multipart/related; boundary=REBOL2.7.6.3.15821639 Content-Length: 5844 Authorization: GoogleLogin auth=
--REBOL2.7.6.3.15821639 Content-Type: application/atom+xml
test
--REBOL2.7.6.3.15821639 Content-Type: application/msword
{\rtf1\ansi\ansicpg1252\uc0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deff0\adeff0{\fonttbl{\f0\fnil\fcharset0 Times New Roman;}}{\colortbl;}{\stylesheet{\s0\snext0\styrsid8412110\sqformat\spriority0\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Normal;}{*\cs10\additive\ssemihidden\spriority0 Default Paragraph Font;}}{*\generator Aspose.Words for Java 3.0.0.0;}{\info{\title 12 Shirley Street}\version0\edmins0\nofpages0\nofwords0\nofchars0\nofcharsws0}\deflang1033\deflangfe2052\adeflang1025\jexpand\showxmlerrors1\viewscale100\fet0\widowctrl\nospaceforul\nolnht adjtbl\alntblind\lyttblrtgr\nogrowautofit\dntblnsbdb\noxlattoyen\wrppunct\nobrkwrptbl\expshrtn\snaptogridincell\asianbrkrule\htmautsp\noultrlspc\useltbaln\splytwnine\ftnlytwnine\lytcalctblwd\allowfieldendsel\newtblstyruls\lnbrkrule\formshade\nojkernpunct\dghspace180\dgvspace180\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1\dgmargin\pgbrdrhead\pgbrdrfoot\sectd\ltrsect\sectdefaultcl\pard\plain\itap0\s0\ltrpar\li0\lin0\ri0\rin0\ql\faau to\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 12 Shirley Street }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Karori }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Wellington 6012 }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrc h\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 $date }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\ lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Dear $provider }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Re: SANDRA JURY 14-Dec-1963 }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faau to\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Here with is my template. }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\p ar}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 Yours sincerely }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 SANDRA JURY }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}\pard\plain\itap0\s0\sa280\saauto 1\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049 \line }{\rtlch\alang1025\afs24\ltrch\fs24\lang1049\langnp1049\par}{*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept}}}
--REBOL2.7.6.3.15821639--
HTTP/1.1 201 Created Content-Type: application/atom+xml; charset=UTF-8 Expires: Fri, 25 Sep 2009 20:18:00 GMT Date: Fri, 25 Sep 2009 20:18:00 GMT Vary: Accept, X-GData-Authorization, GData-Version GData-Version: 1.0 Location: http://docs.google.com/feeds/documents/private/full/document%3A0AaELdnC15jkoZGduejVrYnNfMjcxY3g1dDdjZGc/g01dkf4x Content-Location: http://docs.google.com/feeds/documents/private/full/document%3A0AaELdnC15jkoZGduejVrYnNfMjcxY3g1dDdjZGc/g01dkf4x X-Content-Type-Options: nosniff X-XSS-Protection: 0 Server: GFE/2.0 Via: 1.1 bc6 Cache-Control: private, max-age=0, must-revalidate, no-transform, proxy-revalidate Connection: close
http://docs.google.com/feeds/documents/private/full/document%3A0AaELdnC15jkoZGduejVrYnNfMjcxY3g1dDdjZGc2009-09 -25T20:17:59.385Z2009-09-25T20:17:59.389Ztestcompkaroridontspamme@gmail.comdocument:0AaELdnC15jkoZGduejVrYnNfMjcxY3g1dDdjZGccompkaroridontspamme@gmail.com2009-09-25T20:17:59.451Z0