1 /*jslint 
  2 browser: true,
  3 nomen: false,
  4 debug: true,
  5 forin: true,
  6 undef: true,
  7 white: false,
  8 onevar: false 
  9  */
 10 var sc, DOMParser, jQuery;
 11 
 12 
 13 /**
 14  * An image uploader library for SpazCore. Probably this will supercede spazfileuploader.js
 15  * @param {object} [opts] options hash
 16  * @param {object} [opts.auth_obj] A SpazAuth object that's filled with proper authentication info
 17  * @param {string} [opts.username] a username, in case we're doing that kind of thing
 18  * @param {string} [opts.password] a password, in case we're doing that kind of thing
 19  * @param {string} [opts.auth_method] the method of authentication: 'echo' or 'basic'. Default is 'echo'
 20  * @param {object} [opts.extra] Extra params to pass in the upload request
 21  * @constructor
 22  */
 23 var SpazImageUploader = function(opts) {
 24     if (opts) {
 25         this.setOpts(opts);
 26     }
 27 };
 28 
 29 
 30 /**
 31  * this lets us set options after instantiation 
 32  * @param {object} opts options hash
 33  * @param {object} [opts.auth_obj] A SpazAuth object that's filled with proper authentication info
 34  * @param {string} [opts.username] a username, in case we're doing that kind of thing
 35  * @param {string} [opts.password] a password, in case we're doing that kind of thing
 36  * @param {string} [opts.auth_method] the method of authentication: 'echo' or 'basic'. Default is 'echo'
 37  * @param {string} [opts.statusnet_api_base] the api base URL for statusnet, if that service is used
 38  * @param {object} [opts.extra] Extra params to pass in the upload request
 39  */
 40 SpazImageUploader.prototype.setOpts = function(opts) {
 41     this.opts = sch.defaults({
 42         'extra':{},
 43         'auth_obj':null,
 44         'username':null,
 45         'password':null,
 46         'auth_method':'echo', // 'echo' or 'basic'
 47 		'statusnet_api_base':null // only used by statusnet
 48     }, opts);
 49 };
 50 
 51 /**
 52  * returns an array of labels for the services 
 53  * @return array
 54  */
 55 SpazImageUploader.prototype.getServiceLabels = function() {
 56 	var labels = [];
 57 	for(var key in this.services) {
 58 		labels.push(key);
 59 	}
 60 	return labels;
 61 };
 62 
 63 /**
 64  * a hash of service objects. Each object has a URL endpoint, a parseResponse callback, and an optional "extra" set of params to pass on upload
 65  *	parseResponse should return one of these key/val pairs:
 66  *	- {'url':'http://foo.bar/XXXX'}
 67  *	- {'error':'Error message'}
 68  */
 69 SpazImageUploader.prototype.services = {
 70 	'drippic' : {
 71 		'url' : 'http://drippic.com/drippic2/upload',
 72 		'parseResponse': function(data) {
 73 			
 74 			var parser=new DOMParser();
 75 			xmldoc = parser.parseFromString(data,"text/xml");
 76 
 77 			var status;
 78 			var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes;
 79 			status = rspAttr.getNamedItem("stat").nodeValue;
 80 			
 81 			if (status == 'ok') {
 82 				var mediaurl = $(xmldoc).find('mediaurl').text();
 83 				return {'url':mediaurl};
 84 			} else {
 85 				var errMsg;
 86 				if (xmldoc.getElementsByTagName("err")[0]) {
 87 					errMsg = xmldoc.getElementsByTagName("err")[0].childNodes[0].nodeValue;
 88 				} else {
 89 					errMsg = xmldoc.getElementsByTagName("error")[0].childNodes[0].nodeValue;
 90 				}
 91 				
 92 				sch.error(errMsg);
 93 				return {'error':errMsg};
 94 			}
 95 		}
 96 	},
 97 	'pikchur' : {
 98 		'url'  : 'http://api.pikchur.com/simple/upload',
 99 		'extra': {
100 			'api_key':'MzTrvEd/uPNjGDabr539FA',
101 			'source':'NjMw'
102 		},
103 		'parseResponse': function(data) {
104 			var parser=new DOMParser();
105 			xmldoc = parser.parseFromString(data,"text/xml");
106 	
107 			var status;
108 			var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes;
109 			if (rspAttr.getNamedItem("status")) {
110 				status = rspAttr.getNamedItem("status").nodeValue;
111 			} else if(rspAttr.getNamedItem("stat")) {
112 				status = rspAttr.getNamedItem("stat").nodeValue;
113 			} else {
114 				status = 'fuck I wish they would use the same goddamn nodenames';
115 			}
116 			
117 			if (status == 'ok') {
118 				var mediaurl = $(xmldoc).find('mediaurl').text();
119 				return {'url':mediaurl};
120 			} else {
121 				var errAttributes;
122 				if (xmldoc.getElementsByTagName("err")[0]) {
123 					errAttributes = xmldoc.getElementsByTagName("err")[0].attributes;
124 				} else {
125 					errAttributes = xmldoc.getElementsByTagName("error")[0].attributes;
126 				}
127 				
128 				sch.error(errAttributes);
129 				errMsg = errAttributes.getNamedItem("msg").nodeValue;
130 				sch.error(errMsg);
131 				return {'error':errMsg};
132 			}
133 		}
134 	},
135 	/*
136 		Removed yfrog for now because their oAuth Echo stuff never seems to work.
137 		Not sure if it's my code or theirs
138 	*/
139     // 'yfrog' : {
140     //     'url' : 'http://yfrog.com/api/xauth_upload',
141     //     'extra': {
142     //         'key':'579HINUYe8d826dd61808f2580cbda7f13433310'
143     //     },
144     //     'parseResponse': function(data) {
145     //         
146     //         var parser=new DOMParser();
147     //         xmldoc = parser.parseFromString(data,"text/xml");
148     // 
149     //         var status;
150     //         var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes;
151     //         status = rspAttr.getNamedItem("stat").nodeValue;
152     //         
153     //         if (status == 'ok') {
154     //             var mediaurl = $(xmldoc).find('mediaurl').text();
155     //             return {'url':mediaurl};
156     //         } else {
157     //             var errAttributes;
158     //             if (xmldoc.getElementsByTagName("err")[0]) {
159     //                 errAttributes = xmldoc.getElementsByTagName("err")[0].attributes;
160     //             } else {
161     //                 errAttributes = xmldoc.getElementsByTagName("error")[0].attributes;
162     //             }
163     //             
164     //             sch.error(errAttributes);
165     //             errMsg = errAttributes.getNamedItem("msg").nodeValue;
166     //             sch.error(errMsg);
167     //             return {'error':errMsg};
168     //         }
169     //         
170     //     }
171     // },
172 	'twitpic' : {
173 		'url' : 'http://api.twitpic.com/2/upload.json',
174 		'extra': {
175 			'key':'3d8f511397248dc913193a6195c4a018'
176 		},
177 		'parseResponse': function(data) {
178 			
179 			if (sch.isString(data)) {
180 				data = sch.deJSON(data);
181 			}
182 			
183 			if (data.url) {
184 				return {'url':data.url};
185 			} else {
186 				return {'error':'unknown error'};
187 			}
188 			
189 		}
190 	},
191 	'twitgoo' : {
192 		'url'  : 'http://twitgoo.com/api/upload',
193 		'extra': {
194 			'format':'xml',
195 			'source':'Spaz',
196 			'source_url':'http://getspaz.com'
197 		},
198 		'parseResponse': function(data) {
199 			
200 			var parser=new DOMParser();
201 			xmldoc = parser.parseFromString(data,"text/xml");
202 
203 			var status;
204 			var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes;
205 			status = rspAttr.getNamedItem("status").nodeValue;
206 
207 			if (status == 'ok') {
208 				var mediaurl = $(xmldoc).find('mediaurl').text();
209 				return {'url':mediaurl};
210 			} else {
211 				var errAttributes;
212 				if (xmldoc.getElementsByTagName("err")[0]) {
213 					errAttributes = xmldoc.getElementsByTagName("err")[0].attributes;
214 				} else {
215 					errAttributes = xmldoc.getElementsByTagName("error")[0].attributes;
216 				}
217 
218 				sch.error(errAttributes);
219 				errMsg = errAttributes.getNamedItem("msg").nodeValue;
220 				sch.error(errMsg);
221 				return {'error':errMsg};
222 			}
223 			
224 		}
225 	},
226 	'identi.ca' : {
227 		'url'  : 'http://identi.ca/api/statusnet/media/upload',
228 		'parseResponse': function(data) {
229 			
230 			var parser=new DOMParser();
231 			xmldoc = parser.parseFromString(data,"text/xml");
232 
233 			var status;
234 			var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes;
235 			status = rspAttr.getNamedItem("stat").nodeValue;
236 			
237 			if (status == 'ok') {
238 				var mediaurl = $(xmldoc).find('mediaurl').text();
239 				return {'url':mediaurl};
240 			} else {
241 				var errMsg;
242 				if (xmldoc.getElementsByTagName("err")[0]) {
243 					errMsg = xmldoc.getElementsByTagName("err")[0].childNodes[0].nodeValue;
244 				} else {
245 					errMsg = xmldoc.getElementsByTagName("error")[0].childNodes[0].nodeValue;
246 				}
247 				
248 				sch.error(errMsg);
249 				return {'error':errMsg};
250 			}
251 		}
252 	},
253 	'statusnet' : {
254 		'url'  : '/statusnet/media/upload',
255 		'prepForUpload':function() {
256 			if (this.opts.statusnet_api_base) {
257 				this.services.statusnet.url = this.opts.statusnet_api_base + this.services.statusnet.url;
258 			} else {
259 				sch.error('opts.statusnet_api_base must be set to use statusnet uploader service');
260 			}
261 		},
262 		'parseResponse':function(data) {
263 			var parser=new DOMParser();
264 			xmldoc = parser.parseFromString(data,"text/xml");
265 
266 			var status;
267 			var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes;
268 			status = rspAttr.getNamedItem("stat").nodeValue;
269 			
270 			if (status == 'ok') {
271 				var mediaurl = $(xmldoc).find('mediaurl').text();
272 				return {'url':mediaurl};
273 			} else {
274 				var errMsg;
275 				if (xmldoc.getElementsByTagName("err")[0]) {
276 					errMsg = xmldoc.getElementsByTagName("err")[0].childNodes[0].nodeValue;
277 				} else {
278 					errMsg = xmldoc.getElementsByTagName("error")[0].childNodes[0].nodeValue;
279 				}
280 				
281 				sch.error(errMsg);
282 				return {'error':errMsg};
283 			}
284 			
285 		}
286 	}
287 };
288 
289 /**
290  * Retrieves the auth_header 
291  */
292 SpazImageUploader.prototype.getAuthHeader = function() {
293 	
294 	var opts = sch.defaults({
295 		'getEchoHeaderOpts':{}
296 	}, this.opts);
297 	
298 	var auth_header;
299 	var user = opts.username;
300 	var pass = opts.password;
301 	
302 	if (opts.auth_method === 'echo') { // this is Twitter. hopefully
303 
304 		var twit	= new SpazTwit({'auth':opts.auth_obj});
305 		auth_header = twit.getEchoHeader(opts.getEchoHeaderOpts);
306 
307 	} else {
308 		auth_header = opts.auth_obj.signRequest(); // returns basic auth header
309 	}
310 	
311 	sch.error(auth_header);
312 	return auth_header;
313 
314 };
315 
316 
317 /**
318  * this actually does the upload. Well, really it preps the data and uses sc.helpers.HTTPFileUpload 
319  */
320 SpazImageUploader.prototype.upload = function() {
321 
322 	var opts = sch.defaults({
323 		extra:{}
324 	}, this.opts);
325 	
326 	var srvc = this.services[opts.service];
327 
328 	if (srvc.prepForUpload) {
329 		srvc.prepForUpload.call(this);
330 	}
331 
332 	/*
333 		file url
334 	*/
335 	opts.url      = srvc.url;
336 	if (srvc.extra) {
337 		opts.extra = jQuery.extend(opts.extra, srvc.extra);
338 	}
339 	
340 	var onSuccess, rs;
341 	if (srvc.parseResponse) {
342 		/** @ignore */
343 		onSuccess = function(data) {
344 			if (sch.isString(data)) {
345 				rs = srvc.parseResponse.call(srvc, data);
346 				return opts.onSuccess(rs);
347 			} else if (data && data.responseString) { // webOS will return an object, not just the response string
348 				rs = srvc.parseResponse.call(srvc, data.responseString);
349 				return opts.onSuccess(rs);
350 			} else { // I dunno what it is; just pass it to the callback
351 				return opts.onSuccess(data);
352 			}
353 		};
354 	} else {
355 		onSuccess = opts.onSuccess;
356 	}
357 	
358 	/*
359 		get auth stuff
360 	*/
361 	var auth_header;
362     if (opts.service === 'yfrog') {
363 		verify_url  = 'https://api.twitter.com/1/account/verify_credentials.xml';
364 		auth_header = this.getAuthHeader({
365 			'getEchoHeaderOpts': {
366 				'verify_url':verify_url
367 			}
368 		});
369 	} else {
370 		verify_url  = 'https://api.twitter.com/1/account/verify_credentials.json';
371 		auth_header = this.getAuthHeader();
372 	}
373 	
374 	sch.error(auth_header);
375 	if (auth_header.indexOf('Basic ') === 0) {
376 		
377 		opts.username = this.opts.auth_obj.getUsername();
378 		opts.password = this.opts.auth_obj.getPassword();
379 
380 	} else {
381 		opts.headers = {
382 			'X-Auth-Service-Provider': verify_url,
383 			'X-Verify-Credentials-Authorization':auth_header
384 		};
385 		
386 	}
387 	
388 	sc.helpers.HTTPUploadFile(opts, onSuccess, opts.onFailure);
389 	
390 };