2012-11-16 17:01:04 +00:00
|
|
|
/*\
|
|
|
|
title: $:/plugins/tiddlywiki/tiddlyweb/tiddlyweb.js
|
|
|
|
type: application/javascript
|
2012-11-17 20:18:36 +00:00
|
|
|
module-type: syncer
|
2012-11-16 17:01:04 +00:00
|
|
|
|
|
|
|
Main TiddlyWeb integration module
|
|
|
|
|
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
/*global $tw: false */
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/*
|
2012-11-17 20:18:36 +00:00
|
|
|
Creates a TiddlyWebSyncer object
|
2012-11-16 17:01:04 +00:00
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
var TiddlyWebSyncer = function(options) {
|
2012-11-16 17:01:04 +00:00
|
|
|
// Mark us as not logged in
|
|
|
|
$tw.wiki.addTiddler({
|
2012-11-17 20:18:36 +00:00
|
|
|
title: TiddlyWebSyncer.titleIsLoggedIn,
|
2012-11-16 17:01:04 +00:00
|
|
|
text: "no"
|
|
|
|
});
|
|
|
|
// Get the login status
|
2012-11-17 20:18:36 +00:00
|
|
|
this.getStatus();
|
2012-11-17 12:32:51 +00:00
|
|
|
};
|
|
|
|
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.titleIsLoggedIn = "$:/plugins/tiddlyweb/IsLoggedIn";
|
|
|
|
TiddlyWebSyncer.titleUserName = "$:/plugins/tiddlyweb/UserName";
|
|
|
|
|
2012-11-17 12:32:51 +00:00
|
|
|
/*
|
|
|
|
Error handling
|
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.showError = function(error) {
|
2012-11-17 12:32:51 +00:00
|
|
|
alert("TiddlyWeb error: " + error);
|
|
|
|
console.log("TiddlyWeb error: " + error);
|
|
|
|
};
|
|
|
|
|
2012-11-17 20:18:36 +00:00
|
|
|
/*
|
|
|
|
Handle syncer messages
|
|
|
|
*/
|
|
|
|
TiddlyWebSyncer.prototype.handleEvent = function(event) {
|
|
|
|
switch(event.type) {
|
|
|
|
case "tw-login":
|
|
|
|
this.promptLogin();
|
|
|
|
break;
|
|
|
|
case "tw-logout":
|
|
|
|
this.logout();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-17 12:32:51 +00:00
|
|
|
/*
|
|
|
|
Invoke any tiddlyweb-startup modules
|
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.invokeTiddlyWebStartupModules = function(loggedIn) {
|
2012-11-17 12:32:51 +00:00
|
|
|
$tw.modules.forEachModuleOfType("tiddlyweb-startup",function(title,module) {
|
|
|
|
module.startup(loggedIn);
|
2012-11-16 17:01:04 +00:00
|
|
|
});
|
2012-11-17 20:18:36 +00:00
|
|
|
|
2012-11-16 17:01:04 +00:00
|
|
|
};
|
|
|
|
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.getCsrfToken = function() {
|
2012-11-17 12:32:51 +00:00
|
|
|
var regex = /^(?:.*; )?csrf_token=([^(;|$)]*)(?:;|$)/,
|
|
|
|
match = regex.exec(document.cookie),
|
|
|
|
csrf = null;
|
|
|
|
if (match && (match.length === 2)) {
|
|
|
|
csrf = match[1];
|
|
|
|
}
|
|
|
|
return csrf;
|
2012-11-17 20:18:36 +00:00
|
|
|
|
2012-11-17 12:32:51 +00:00
|
|
|
};
|
|
|
|
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.getStatus = function(callback) {
|
2012-11-16 17:01:04 +00:00
|
|
|
// Get status
|
2012-11-17 20:18:36 +00:00
|
|
|
this.httpRequest({
|
2012-11-16 17:01:04 +00:00
|
|
|
url: "http://tw5tiddlyweb.tiddlyspace.com/status",
|
|
|
|
callback: function(err,data) {
|
2012-11-17 12:32:51 +00:00
|
|
|
// Decode the status JSON
|
2012-11-16 17:01:04 +00:00
|
|
|
var json = null;
|
|
|
|
try {
|
|
|
|
json = JSON.parse(data);
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
if(json) {
|
2012-11-17 12:32:51 +00:00
|
|
|
// Check if we're logged in
|
2012-11-16 17:01:04 +00:00
|
|
|
var isLoggedIn = json.username !== "GUEST";
|
2012-11-17 12:32:51 +00:00
|
|
|
// Set the various status tiddlers
|
2012-11-16 17:01:04 +00:00
|
|
|
$tw.wiki.addTiddler({
|
2012-11-17 20:18:36 +00:00
|
|
|
title: TiddlyWebSyncer.titleIsLoggedIn,
|
2012-11-16 17:01:04 +00:00
|
|
|
text: isLoggedIn ? "yes" : "no"
|
|
|
|
});
|
|
|
|
if(isLoggedIn) {
|
|
|
|
$tw.wiki.addTiddler({
|
2012-11-17 20:18:36 +00:00
|
|
|
title: TiddlyWebSyncer.titleUserName,
|
2012-11-16 17:01:04 +00:00
|
|
|
text: json.username
|
|
|
|
});
|
|
|
|
} else {
|
2012-11-17 20:18:36 +00:00
|
|
|
$tw.wiki.deleteTiddler(TiddlyWebSyncer.titleUserName);
|
2012-11-16 17:01:04 +00:00
|
|
|
}
|
|
|
|
}
|
2012-11-17 12:32:51 +00:00
|
|
|
// Invoke the callback if present
|
2012-11-16 17:01:04 +00:00
|
|
|
if(callback) {
|
|
|
|
callback(isLoggedIn,json);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2012-11-17 12:32:51 +00:00
|
|
|
Dispay a password prompt and allow the user to login
|
2012-11-16 17:01:04 +00:00
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.promptLogin = function() {
|
|
|
|
var self = this;
|
|
|
|
this.getStatus(function(isLoggedIn,json) {
|
2012-11-17 12:32:51 +00:00
|
|
|
if(!isLoggedIn) {
|
|
|
|
$tw.passwordPrompt.createPrompt({
|
|
|
|
serviceName: "Login to TiddlySpace",
|
|
|
|
callback: function(data) {
|
2012-11-17 20:18:36 +00:00
|
|
|
self.login(data.username,data.password);
|
2012-11-17 12:32:51 +00:00
|
|
|
return true; // Get rid of the password prompt
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2012-11-16 17:01:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2012-11-17 12:32:51 +00:00
|
|
|
Attempt to login to TiddlyWeb.
|
|
|
|
username: username
|
|
|
|
password: password
|
|
|
|
callback: invoked with arguments (err,isLoggedIn)
|
2012-11-16 17:01:04 +00:00
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.login = function(username,password,callback) {
|
|
|
|
var self = this;
|
|
|
|
var httpRequest = this.httpRequest({
|
2012-11-17 12:32:51 +00:00
|
|
|
url: "http://tw5tiddlyweb.tiddlyspace.com/challenge/tiddlywebplugins.tiddlyspace.cookie_form",
|
|
|
|
type: "POST",
|
|
|
|
data: {
|
|
|
|
user: username,
|
|
|
|
password: password,
|
|
|
|
tiddlyweb_redirect: "/status" // workaround to marginalize automatic subsequent GET
|
|
|
|
},
|
|
|
|
callback: function(err,data) {
|
|
|
|
if(err) {
|
|
|
|
if(callback) {
|
|
|
|
callback(err);
|
|
|
|
}
|
|
|
|
} else {
|
2012-11-17 20:18:36 +00:00
|
|
|
self.getStatus(function(isLoggedIn,json) {
|
2012-11-17 12:32:51 +00:00
|
|
|
if(callback) {
|
|
|
|
callback(null,isLoggedIn);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2012-11-16 17:01:04 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2012-11-17 12:32:51 +00:00
|
|
|
Attempt to log out of TiddlyWeb
|
2012-11-16 17:01:04 +00:00
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.logout = function(options) {
|
2012-11-16 17:01:04 +00:00
|
|
|
options = options || {};
|
2012-11-17 20:18:36 +00:00
|
|
|
var self = this;
|
|
|
|
var httpRequest = this.httpRequest({
|
2012-11-17 12:32:51 +00:00
|
|
|
url: "http://tw5tiddlyweb.tiddlyspace.com/logout",
|
2012-11-16 17:01:04 +00:00
|
|
|
type: "POST",
|
|
|
|
data: {
|
2012-11-17 20:18:36 +00:00
|
|
|
csrf_token: this.getCsrfToken(),
|
2012-11-16 17:01:04 +00:00
|
|
|
tiddlyweb_redirect: "/status" // workaround to marginalize automatic subsequent GET
|
|
|
|
},
|
|
|
|
callback: function(err,data) {
|
|
|
|
if(err) {
|
2012-11-17 20:31:30 +00:00
|
|
|
self.showError("logout error: " + err);
|
2012-11-16 17:01:04 +00:00
|
|
|
} else {
|
2012-11-17 20:31:30 +00:00
|
|
|
self.getStatus();
|
2012-11-16 17:01:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Some quick and dirty HTTP functions; to be refactored later. Options are:
|
|
|
|
url: URL to retrieve
|
|
|
|
type: GET, PUT, POST etc
|
|
|
|
callback: function invoked with (err,data)
|
|
|
|
*/
|
2012-11-17 20:18:36 +00:00
|
|
|
TiddlyWebSyncer.prototype.httpRequest = function(options) {
|
2012-11-16 17:01:04 +00:00
|
|
|
var type = options.type || "GET",
|
|
|
|
client = new XMLHttpRequest(),
|
|
|
|
data = "",
|
|
|
|
f,results;
|
|
|
|
if(options.data) {
|
|
|
|
if(typeof options.data === "string") { // Already a string
|
|
|
|
data = options.data;
|
|
|
|
} else { // A hashmap of strings
|
|
|
|
results = [];
|
|
|
|
for(f in options.data) {
|
|
|
|
if($tw.utils.hop(options.data,f)) {
|
|
|
|
results.push(f + "=" + encodeURIComponent(options.data[f]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data = results.join("&")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
client.onreadystatechange = function() {
|
|
|
|
if(this.readyState === 4) {
|
|
|
|
if(this.status === 200) {
|
|
|
|
// success!
|
|
|
|
options.callback(null,this.responseText);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// something went wrong
|
|
|
|
options.callback(new Error("XMLHttpRequest error: " + this.status));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
client.open(type,options.url,true);
|
|
|
|
if(data) {
|
|
|
|
client.setRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8");
|
|
|
|
}
|
|
|
|
client.send(data);
|
|
|
|
return client;
|
|
|
|
};
|
|
|
|
|
2012-11-17 20:18:36 +00:00
|
|
|
// Only export anything on the browser
|
|
|
|
if($tw.browser) {
|
|
|
|
exports.name = "tiddlywebsyncer";
|
|
|
|
exports.syncer = TiddlyWebSyncer;
|
|
|
|
}
|
|
|
|
|
2012-11-16 17:01:04 +00:00
|
|
|
})();
|