Was this page helpful?

Googledocs

    Table of contents
    No headers
    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............}]
    Was this page helpful?
    Tag page (Edit tags)
    You must login to post a comment.
    Powered by MindTouch Core