open_graph 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,623 @@
1
+ ;(function(window, undefined){
2
+
3
+ // two globals for creating the cookie
4
+ // FB Functions
5
+ function init(data){
6
+ FBWorld.initialized = true;
7
+ state('appId', data.appId);
8
+ }
9
+
10
+ function login(callback){
11
+ if (calledBeforeInit('login')) return;
12
+ if (FBWorld.state('loggedIn')){
13
+ console.log('FB.login() called when user is already connected.');
14
+ if (FBWorld.state('connected')){
15
+ callback(getStatus());
16
+ }else{
17
+ simulatePromptToConnect(callback);
18
+ }
19
+ }else{
20
+ simulatePromptToLogin(callback);
21
+ }
22
+ }
23
+
24
+ function logout(callback){
25
+ if (calledBeforeInit('logout')) return;
26
+ if (!FBWorld.state('loggedIn')) console.log('FB.logout() called without a session.');
27
+ FBWorld.notLoggedIn();
28
+ callback(getStatus());
29
+ }
30
+
31
+ function getLoginStatus(callback, perms){
32
+ if (calledBeforeInit('getLoginStatus')) return;
33
+ callback(getStatus());
34
+ }
35
+
36
+ function getSession(){
37
+ if (calledBeforeInit('getSession')) return false;
38
+ return getStatus().session;
39
+ }
40
+
41
+ // FBWorld Functions
42
+ //3 states: loggedOut, loggedIn, connected
43
+ function state(){
44
+ var theState = JSON.parse(FBWorld.Helpers.makeMeACookie('fb-stub') || '{}');
45
+ if (arguments.length === 0) return theState;
46
+ if (arguments.length === 1) return theState[arguments[0]];
47
+ if (arguments.length === 2) {
48
+ theState[arguments[0]] = arguments[1];
49
+ FBWorld.Helpers.makeMeACookie('fb-stub', JSON.stringify(theState));
50
+ return arguments[1];
51
+ }
52
+ }
53
+
54
+ function uid(){
55
+ return FBWorld.state('uid');
56
+ }
57
+
58
+ function setUid(newUid){
59
+ return FBWorld.state('uid', newUid);
60
+ }
61
+
62
+ function setSecret(newSecret){
63
+ return state('secret', newSecret);
64
+ }
65
+
66
+ function loggedIn(){
67
+ createConnectedCookie();
68
+ FBWorld.state('loggedIn', true);
69
+ return true;
70
+ }
71
+
72
+ function notLoggedIn(){
73
+ deleteConnectedCookie();
74
+ FBWorld.state('loggedIn', false);
75
+ }
76
+
77
+ function connected(){
78
+ createConnectedCookie();
79
+ FBWorld.state('connected', true);
80
+ }
81
+
82
+ function notConnected(){
83
+ deleteConnectedCookie();
84
+ FBWorld.state('connected', false);
85
+ }
86
+
87
+ FB = { // Emulates the FB API
88
+ getLoginStatus : getLoginStatus,
89
+ logout : logout,
90
+ login : login,
91
+ init : init,
92
+ getSession : getSession
93
+ };
94
+
95
+ FBWorld = { // used to set the state of Facebook
96
+ state : state,
97
+ loggedIn : loggedIn,
98
+ notLoggedIn : notLoggedIn,
99
+ setUid : setUid,
100
+ setSecret : setSecret,
101
+ uid : uid,
102
+ connected : connected,
103
+ notConnected : notConnected,
104
+
105
+ initialized : false,
106
+ beingPromptedToLogIn : false,
107
+ beingPromptedToLogInCallback : undefined,
108
+ // this will come later, no need for it now
109
+ // successfullyLogin: successfullyLogin,
110
+ // failToLogin: failToLogin,
111
+
112
+ beingPromptedToConnect : false,
113
+ beingPromptedToConnectInCallback : undefined,
114
+ allowConnection : allowConnection,
115
+ denyConnection : denyConnection
116
+ };
117
+
118
+ // PRIVATE FUNCTIONS
119
+
120
+ function getStatus(includePerms) {
121
+ var theState = FBWorld.state();
122
+
123
+ // Connected
124
+ if (theState.loggedIn && theState.connected){
125
+ var status = {
126
+ status: "connected",
127
+ session: createConnectedCookie()
128
+ };
129
+
130
+ if (includePerms) status.perms = JSON.stringify(theState.perms);
131
+ return status;
132
+ }
133
+
134
+ // not connected
135
+ if (theState.loggedIn && !theState.connected){
136
+ return {
137
+ perms: null,
138
+ session: null,
139
+ status: 'notConnected'
140
+ };
141
+ }
142
+
143
+ // not logged in
144
+ if (!theState.loggedIn) {
145
+ return {
146
+ perms: null,
147
+ session: null,
148
+ status: 'unknown'
149
+ };
150
+ }
151
+
152
+ // var selectedPerms = '{"extended":["status_update","photo_upload","video_upload","offline_access","email","create_note","share_item","publish_stream","contact_email"],"user":["manage_friendlists","create_event","read_requests","manage_pages"],"friends":[]}';
153
+
154
+ };
155
+
156
+ function calledBeforeInit() {
157
+ if (FBWorld.initialized) return false;
158
+ console.log("FB."+meth+" called before FB.init");
159
+ return true;
160
+ }
161
+
162
+ function simulatePromptToLogin(callback) {
163
+ // simulate being prompted to log in
164
+ FBWorld.beingPromptedToLogIn = true;
165
+ FBWorld.beingPromptedToLogInCallback = function(approved){
166
+ FBWorld.beingPromptedToLogin = false;
167
+ FBWorld.beingPromptedToLoginCallback = undefined;
168
+ if(approved){
169
+ FBWorld.loggedIn();
170
+ if (!FBWorld.state('connected')){
171
+ simulatePromptToConnect(callback);
172
+ }else{
173
+ callback(getStatus());
174
+ }
175
+ }else{
176
+ FBWorld.notLoggedIn();
177
+ callback(getStatus());
178
+ }
179
+
180
+ };
181
+ };
182
+
183
+ function simulatePromptToConnect(callback) {
184
+ // simulate being prompted to connect
185
+ FBWorld.beingPromptedToConnect = true;
186
+ FBWorld.beingPromptedToConnectCallback = function(approved){
187
+ approved ? FBWorld.connected() : FBWorld.notConnected();
188
+ FBWorld.beingPromptedToConnect = false;
189
+ FBWorld.beingPromptedToConnectCallback = undefined;
190
+ callback(getStatus());
191
+ };
192
+ };
193
+
194
+ function allowConnection() {
195
+ if (!FBWorld.beingPromptedToConnect) throw "you are not being prompted to connect";
196
+ FBWorld.beingPromptedToConnectCallback(true);
197
+ };
198
+
199
+ function denyConnection() {
200
+ if (!FBWorld.beingPromptedToConnect) throw "you are not being prompted to connect";
201
+ FBWorld.beingPromptedToConnectCallback(false);
202
+ };
203
+
204
+ var cookieOptions = { path: '/', domain: window.location.hostname.replace(/^www/, '')};
205
+
206
+ // cookie looks like this: (with the quotes): "access_token=theToken&base_domain=local-change.org&expires=0&secret=theSecret&session_key=theSessionKeysig=theSig-Hashed&uid=theUID"
207
+ function createConnectedCookie(){
208
+ var defaultValues = {
209
+ access_token: 'theToken',
210
+ base_domain: window.location.hostname.replace(/^www\./, ''),
211
+ secret: state('secret') || 'theSecret',
212
+ session_key: 'sessionKey',
213
+ expires: 0,
214
+ uid: state('uid')
215
+ };
216
+ if (uid() != null){
217
+ defaultValues.uid = uid();
218
+ }
219
+ var theState = addSig(defaultValues);
220
+ FBWorld.Helpers.makeMeACookie('fbs_'+state('appId'), cookieToString(theState), cookieOptions);
221
+ return theState;
222
+ }
223
+
224
+ function addSig(theState){
225
+ theState['sig'] = FBWorld.Helpers.md5.hex_md5(cookieToString(theState, true));
226
+ return theState;
227
+ }
228
+
229
+ function cookieToString(theState, forSig){
230
+ var response = [], fields;
231
+ if (typeof forSig == 'undefined')
232
+ fields = ['access_token', 'base_domain', 'expires', 'secret', 'session_key', 'sig', 'uid'];
233
+ else
234
+ fields = ['access_token', 'base_domain', 'expires', 'secret', 'session_key', 'uid'];
235
+ for (var i =0; i < fields.length; i++){
236
+ var field = fields[i];
237
+ response.push(field + '=' + theState[field]);
238
+ }
239
+ if (typeof forSig != 'undefined'){
240
+ response = response.join('') + theState['secret'];
241
+ }else{
242
+ response = response.join('&');
243
+ }
244
+ return response;
245
+ }
246
+ function deleteConnectedCookie(){
247
+ FBWorld.Helpers.makeMeACookie('fbs_'+state('appId'), null, cookieOptions);
248
+ }
249
+
250
+
251
+ })(this);
252
+ FBWorld.Helpers = {};
253
+ setTimeout(function() { if (typeof fbAsyncInit === 'function') fbAsyncInit(); }, 1);
254
+
255
+ /**
256
+ * Cookie plugin
257
+ *
258
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
259
+ * Dual licensed under the MIT and GPL licenses:
260
+ * http://www.opensource.org/licenses/mit-license.php
261
+ * http://www.gnu.org/licenses/gpl.html
262
+ *
263
+ */
264
+
265
+ /**
266
+ * Create a cookie with the given name and value and other optional parameters.
267
+ *
268
+ * @example $.cookie('the_cookie', 'the_value');
269
+ * @desc Set the value of a cookie.
270
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
271
+ * @desc Create a cookie with all available options.
272
+ * @example $.cookie('the_cookie', 'the_value');
273
+ * @desc Create a session cookie.
274
+ * @example $.cookie('the_cookie', null);
275
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
276
+ * used when the cookie was set.
277
+ *
278
+ * @param String name The name of the cookie.
279
+ * @param String value The value of the cookie.
280
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
281
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
282
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
283
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
284
+ * when the the browser exits.
285
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
286
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
287
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
288
+ * require a secure protocol (like HTTPS).
289
+ * @type undefined
290
+ *
291
+ * @name $.cookie
292
+ * @cat Plugins/Cookie
293
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
294
+ */
295
+
296
+ /**
297
+ * Get the value of a cookie with the given name.
298
+ *
299
+ * @example $.cookie('the_cookie');
300
+ * @desc Get the value of a cookie.
301
+ *
302
+ * @param String name The name of the cookie.
303
+ * @return The value of the cookie.
304
+ * @type String
305
+ *
306
+ * @name $.cookie
307
+ * @cat Plugins/Cookie
308
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
309
+ */
310
+
311
+ // Modified to make it not use jquery
312
+ FBWorld.Helpers.makeMeACookie = function(name, value, options) {
313
+ if (typeof value != 'undefined') { // name and value given, set cookie
314
+ options = options || {};
315
+ if (value === null) {
316
+ value = '';
317
+ options.expires = -1;
318
+ }
319
+ var expires = '';
320
+ if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
321
+ var date;
322
+ if (typeof options.expires == 'number') {
323
+ date = new Date();
324
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
325
+ } else {
326
+ date = options.expires;
327
+ }
328
+ expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
329
+ }
330
+ // CAUTION: Needed to parenthesize options.path and options.domain
331
+ // in the following expressions, otherwise they evaluate to undefined
332
+ // in the packed version for some reason...
333
+ var path = options.path ? '; path=' + (options.path) : '';
334
+ var domain = options.domain ? '; domain=' + (options.domain) : '';
335
+ var secure = options.secure ? '; secure' : '';
336
+ document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
337
+ } else { // only name given, get cookie
338
+ var cookieValue = null;
339
+ if (document.cookie && document.cookie != '') {
340
+ var cookies = document.cookie.split(';');
341
+ for (var i = 0; i < cookies.length; i++) {
342
+ var cookie = FBWorld.Helpers.trim(cookies[i]);
343
+ // Does this cookie string begin with the name we want?
344
+ if (cookie.substring(0, name.length + 1) == (name + '=')) {
345
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
346
+ break;
347
+ }
348
+ }
349
+ }
350
+ return cookieValue;
351
+ }
352
+ };
353
+
354
+ //Taken from jQuery
355
+ FBWorld.Helpers.trim = function( text ) {
356
+ return text == null ?
357
+ "" :
358
+ text.toString().replace( /^\s+/, "" ).replace( /\s+$/, "" );
359
+ };
360
+ //md5 generation of sig (THANK YOU INTERNETS)
361
+ FBWorld.Helpers.md5 = (function(){
362
+
363
+ /*
364
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
365
+ * Digest Algorithm, as defined in RFC 1321.
366
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
367
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
368
+ * Distributed under the BSD License
369
+ * See http://pajhome.org.uk/crypt/md5 for more info.
370
+ */
371
+
372
+ /*
373
+ * Configurable variables. You may need to tweak these to be compatible with
374
+ * the server-side, but the defaults work in most cases.
375
+ */
376
+ var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
377
+ var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
378
+
379
+ /*
380
+ * These are the functions you'll usually want to call
381
+ * They take string arguments and return either hex or base-64 encoded strings
382
+ */
383
+ function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
384
+
385
+
386
+ /*
387
+ * Calculate the MD5 of a raw string
388
+ */
389
+ function rstr_md5(s)
390
+ {
391
+ return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
392
+ }
393
+
394
+ /*
395
+ * Convert a raw string to a hex string
396
+ */
397
+ function rstr2hex(input)
398
+ {
399
+ try { hexcase; } catch(e) { hexcase=0; }
400
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
401
+ var output = "";
402
+ var x;
403
+ for(var i = 0; i < input.length; i++)
404
+ {
405
+ x = input.charCodeAt(i);
406
+ output += hex_tab.charAt((x >>> 4) & 0x0F)
407
+ + hex_tab.charAt( x & 0x0F);
408
+ }
409
+ return output;
410
+ }
411
+
412
+
413
+
414
+ /*
415
+ * Encode a string as utf-8.
416
+ * For efficiency, this assumes the input is valid utf-16.
417
+ */
418
+ function str2rstr_utf8(input)
419
+ {
420
+ var output = "";
421
+ var i = -1;
422
+ var x, y;
423
+
424
+ while(++i < input.length)
425
+ {
426
+ /* Decode utf-16 surrogate pairs */
427
+ x = input.charCodeAt(i);
428
+ y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
429
+ if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
430
+ {
431
+ x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
432
+ i++;
433
+ }
434
+
435
+ /* Encode output as utf-8 */
436
+ if(x <= 0x7F)
437
+ output += String.fromCharCode(x);
438
+ else if(x <= 0x7FF)
439
+ output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
440
+ 0x80 | ( x & 0x3F));
441
+ else if(x <= 0xFFFF)
442
+ output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
443
+ 0x80 | ((x >>> 6 ) & 0x3F),
444
+ 0x80 | ( x & 0x3F));
445
+ else if(x <= 0x1FFFFF)
446
+ output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
447
+ 0x80 | ((x >>> 12) & 0x3F),
448
+ 0x80 | ((x >>> 6 ) & 0x3F),
449
+ 0x80 | ( x & 0x3F));
450
+ }
451
+ return output;
452
+ }
453
+
454
+
455
+ /*
456
+ * Convert a raw string to an array of little-endian words
457
+ * Characters >255 have their high-byte silently ignored.
458
+ */
459
+ function rstr2binl(input)
460
+ {
461
+ var output = Array(input.length >> 2);
462
+ var i;
463
+ for(i = 0; i < output.length; i++)
464
+ output[i] = 0;
465
+ for(i = 0; i < input.length * 8; i += 8)
466
+ output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
467
+ return output;
468
+ }
469
+
470
+ /*
471
+ * Convert an array of little-endian words to a string
472
+ */
473
+ function binl2rstr(input)
474
+ {
475
+ var output = "";
476
+ for(var i = 0; i < input.length * 32; i += 8)
477
+ output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
478
+ return output;
479
+ }
480
+
481
+ /*
482
+ * Calculate the MD5 of an array of little-endian words, and a bit length.
483
+ */
484
+ function binl_md5(x, len)
485
+ {
486
+ /* append padding */
487
+ x[len >> 5] |= 0x80 << ((len) % 32);
488
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
489
+
490
+ var a = 1732584193;
491
+ var b = -271733879;
492
+ var c = -1732584194;
493
+ var d = 271733878;
494
+
495
+ for(var i = 0; i < x.length; i += 16)
496
+ {
497
+ var olda = a;
498
+ var oldb = b;
499
+ var oldc = c;
500
+ var oldd = d;
501
+
502
+ a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
503
+ d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
504
+ c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
505
+ b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
506
+ a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
507
+ d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
508
+ c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
509
+ b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
510
+ a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
511
+ d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
512
+ c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
513
+ b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
514
+ a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
515
+ d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
516
+ c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
517
+ b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
518
+
519
+ a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
520
+ d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
521
+ c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
522
+ b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
523
+ a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
524
+ d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
525
+ c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
526
+ b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
527
+ a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
528
+ d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
529
+ c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
530
+ b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
531
+ a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
532
+ d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
533
+ c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
534
+ b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
535
+
536
+ a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
537
+ d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
538
+ c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
539
+ b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
540
+ a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
541
+ d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
542
+ c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
543
+ b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
544
+ a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
545
+ d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
546
+ c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
547
+ b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
548
+ a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
549
+ d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
550
+ c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
551
+ b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
552
+
553
+ a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
554
+ d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
555
+ c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
556
+ b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
557
+ a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
558
+ d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
559
+ c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
560
+ b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
561
+ a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
562
+ d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
563
+ c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
564
+ b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
565
+ a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
566
+ d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
567
+ c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
568
+ b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
569
+
570
+ a = safe_add(a, olda);
571
+ b = safe_add(b, oldb);
572
+ c = safe_add(c, oldc);
573
+ d = safe_add(d, oldd);
574
+ }
575
+ return Array(a, b, c, d);
576
+ }
577
+
578
+ /*
579
+ * These functions implement the four basic operations the algorithm uses.
580
+ */
581
+ function md5_cmn(q, a, b, x, s, t)
582
+ {
583
+ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
584
+ }
585
+ function md5_ff(a, b, c, d, x, s, t)
586
+ {
587
+ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
588
+ }
589
+ function md5_gg(a, b, c, d, x, s, t)
590
+ {
591
+ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
592
+ }
593
+ function md5_hh(a, b, c, d, x, s, t)
594
+ {
595
+ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
596
+ }
597
+ function md5_ii(a, b, c, d, x, s, t)
598
+ {
599
+ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
600
+ }
601
+
602
+ /*
603
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
604
+ * to work around bugs in some JS interpreters.
605
+ */
606
+ function safe_add(x, y)
607
+ {
608
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
609
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
610
+ return (msw << 16) | (lsw & 0xFFFF);
611
+ }
612
+
613
+ /*
614
+ * Bitwise rotate a 32-bit number to the left.
615
+ */
616
+ function bit_rol(num, cnt)
617
+ {
618
+ return (num << cnt) | (num >>> (32 - cnt));
619
+ }
620
+ return {
621
+ hex_md5: hex_md5
622
+ };
623
+ })();
@@ -1,3 +1,3 @@
1
1
  module OpenGraph
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.rubyforge_project = "open_graph"
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
+ s.files << 'facebook-stub/facebook-stub.js'
18
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
21
  s.require_paths = ["lib"]
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 2
10
- version: 0.0.2
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Change.org Engineering
@@ -42,6 +42,7 @@ files:
42
42
  - lib/open_graph/test/facebook_stub/picture.png
43
43
  - lib/open_graph/version.rb
44
44
  - open_graph.gemspec
45
+ - facebook-stub/facebook-stub.js
45
46
  has_rdoc: true
46
47
  homepage: https://github.com/change/open_graph
47
48
  licenses: []