diff --git a/src/node/db/API.js b/src/node/db/API.js index 7a9ce41fa..37dbabe0f 100644 --- a/src/node/db/API.js +++ b/src/node/db/API.js @@ -19,6 +19,7 @@ */ var ERR = require("async-stacktrace"); +var semver = require("semver"); var customError = require("../utils/customError"); var padManager = require("./PadManager"); var padMessageHandler = require("../handler/PadMessageHandler"); @@ -32,43 +33,52 @@ var importHtml = require("../utils/ImportHtml"); var cleanText = require("./Pad").cleanText; var PadDiff = require("../utils/padDiff"); +var API = { + ">=1": {}, + ">=1.1": {}, + ">=1.2": {}, + ">=1.2.1": {}, + ">=1.2.7": {} +}; + + /**********************/ /**GROUP FUNCTIONS*****/ /**********************/ -exports.listAllGroups = groupManager.listAllGroups; -exports.createGroup = groupManager.createGroup; -exports.createGroupIfNotExistsFor = groupManager.createGroupIfNotExistsFor; -exports.deleteGroup = groupManager.deleteGroup; -exports.listPads = groupManager.listPads; -exports.createGroupPad = groupManager.createGroupPad; +API[">=1.1"].listAllGroups = groupManager.listAllGroups; +API[">=1"].createGroup = groupManager.createGroup; +API[">=1"].createGroupIfNotExistsFor = groupManager.createGroupIfNotExistsFor; +API[">=1"].deleteGroup = groupManager.deleteGroup; +API[">=1"].listPads = groupManager.listPads; +API[">=1"].createGroupPad = groupManager.createGroupPad; /**********************/ /**PADLIST FUNCTION****/ /**********************/ -exports.listAllPads = padManager.listAllPads; +API[">=1.2.1"].listAllPads = padManager.listAllPads; /**********************/ /**AUTHOR FUNCTIONS****/ /**********************/ -exports.createAuthor = authorManager.createAuthor; -exports.createAuthorIfNotExistsFor = authorManager.createAuthorIfNotExistsFor; -exports.getAuthorName = authorManager.getAuthorName; -exports.listPadsOfAuthor = authorManager.listPadsOfAuthor; -exports.padUsers = padMessageHandler.padUsers; -exports.padUsersCount = padMessageHandler.padUsersCount; +API[">=1"].createAuthor = authorManager.createAuthor; +API[">=1"].createAuthorIfNotExistsFor = authorManager.createAuthorIfNotExistsFor; +API[">=1.1"].getAuthorName = authorManager.getAuthorName; +API[">=1"].listPadsOfAuthor = authorManager.listPadsOfAuthor; +API[">=1.1"].padUsers = padMessageHandler.padUsers; +API[">=1"].padUsersCount = padMessageHandler.padUsersCount; /**********************/ /**SESSION FUNCTIONS***/ /**********************/ -exports.createSession = sessionManager.createSession; -exports.deleteSession = sessionManager.deleteSession; -exports.getSessionInfo = sessionManager.getSessionInfo; -exports.listSessionsOfGroup = sessionManager.listSessionsOfGroup; -exports.listSessionsOfAuthor = sessionManager.listSessionsOfAuthor; +API[">=1"].createSession = sessionManager.createSession; +API[">=1"].deleteSession = sessionManager.deleteSession; +API[">=1"].getSessionInfo = sessionManager.getSessionInfo; +API[">=1"].listSessionsOfGroup = sessionManager.listSessionsOfGroup; +API[">=1"].listSessionsOfAuthor = sessionManager.listSessionsOfAuthor; /************************/ /**PAD CONTENT FUNCTIONS*/ @@ -82,7 +92,7 @@ Example returns: {code: 0, message:"ok", data: {text:"Welcome Text"}} {code: 1, message:"padID does not exist", data: null} */ -exports.getText = function(padID, rev, callback) +API[">=1"].getText = function(padID, rev, callback) { //check if rev is set if(typeof rev == "function") @@ -162,7 +172,7 @@ Example returns: {code: 1, message:"padID does not exist", data: null} {code: 1, message:"text too long", data: null} */ -exports.setText = function(padID, text, callback) +API[">=1"].setText = function(padID, text, callback) { //text is required if(typeof text != "string") @@ -192,7 +202,7 @@ Example returns: {code: 0, message:"ok", data: {text:"Welcome Text"}} {code: 1, message:"padID does not exist", data: null} */ -exports.getHTML = function(padID, rev, callback) +function getHTML(padID, rev, wrapBody, callback) { if(typeof rev == "function") { @@ -243,8 +253,10 @@ exports.getHTML = function(padID, rev, callback) exportHtml.getPadHTML(pad, rev, function(err, html) { if(ERR(err, callback)) return; - html = "" +html; // adds HTML head - html += ""; + if(wrapBody) { + html = "" +html; // adds HTML head + html += ""; + } data = {html: html}; callback(null, data); }); @@ -255,8 +267,10 @@ exports.getHTML = function(padID, rev, callback) exportHtml.getPadHTML(pad, undefined, function (err, html) { if(ERR(err, callback)) return; - html = "" +html; // adds HTML head - html += ""; + if(wrapBody){ + html = "" +html; // adds HTML head + html += ""; + } data = {html: html}; callback(null, data); }); @@ -264,7 +278,12 @@ exports.getHTML = function(padID, rev, callback) }); } -exports.setHTML = function(padID, html, callback) +API[">=1"].getHTML = function(padID, rev, callback){ return getHTML(padID, rev, false, callback); }; + +// this overrides the getHTML function for api version >= 1.2.7 +API[">=1.2.7"].getHTML = function(padID, rev, callback){ return getHTML(padID, rev, true, callback); }; + +API[">=1"].setHTML = function(padID, html, callback) { //get the pad getPadSafe(padID, true, function(err, pad) @@ -296,7 +315,7 @@ Example returns: {code: 1, message:"padID does not exist", data: null} */ -exports.getChatHistory = function(padID, start, end, callback) +API[">=1.2.7"].getChatHistory = function(padID, start, end, callback) { if(start && end) { @@ -363,7 +382,7 @@ Example returns: {code: 0, message:"ok", data: {revisions: 56}} {code: 1, message:"padID does not exist", data: null} */ -exports.getRevisionsCount = function(padID, callback) +API[">=1"].getRevisionsCount = function(padID, callback) { //get the pad getPadSafe(padID, true, function(err, pad) @@ -382,7 +401,7 @@ Example returns: {code: 0, message:"ok", data: {lastEdited: 1340815946602}} {code: 1, message:"padID does not exist", data: null} */ -exports.getLastEdited = function(padID, callback) +API[">=1"].getLastEdited = function(padID, callback) { //get the pad getPadSafe(padID, true, function(err, pad) @@ -403,7 +422,7 @@ Example returns: {code: 0, message:"ok", data: null} {code: 1, message:"pad does already exist", data: null} */ -exports.createPad = function(padID, text, callback) +API[">=1"].createPad = function(padID, text, callback) { //ensure there is no $ in the padID if(padID && padID.indexOf("$") != -1) @@ -428,7 +447,7 @@ Example returns: {code: 0, message:"ok", data: null} {code: 1, message:"padID does not exist", data: null} */ -exports.deletePad = function(padID, callback) +API[">=1"].deletePad = function(padID, callback) { getPadSafe(padID, true, function(err, pad) { @@ -446,7 +465,7 @@ Example returns: {code: 0, message:"ok", data: null} {code: 1, message:"padID does not exist", data: null} */ -exports.getReadOnlyID = function(padID, callback) +API[">=1"].getReadOnlyID = function(padID, callback) { //we don't need the pad object, but this function does all the security stuff for us getPadSafe(padID, true, function(err) @@ -470,7 +489,7 @@ Example returns: {code: 0, message:"ok", data: null} {code: 1, message:"padID does not exist", data: null} */ -exports.setPublicStatus = function(padID, publicStatus, callback) +API[">=1"].setPublicStatus = function(padID, publicStatus, callback) { //ensure this is a group pad if(padID && padID.indexOf("$") == -1) @@ -503,7 +522,7 @@ Example returns: {code: 0, message:"ok", data: {publicStatus: true}} {code: 1, message:"padID does not exist", data: null} */ -exports.getPublicStatus = function(padID, callback) +API[">=1"].getPublicStatus = function(padID, callback) { //ensure this is a group pad if(padID && padID.indexOf("$") == -1) @@ -529,7 +548,7 @@ Example returns: {code: 0, message:"ok", data: null} {code: 1, message:"padID does not exist", data: null} */ -exports.setPassword = function(padID, password, callback) +API[">=1"].setPassword = function(padID, password, callback) { //ensure this is a group pad if(padID && padID.indexOf("$") == -1) @@ -558,7 +577,7 @@ Example returns: {code: 0, message:"ok", data: {passwordProtection: true}} {code: 1, message:"padID does not exist", data: null} */ -exports.isPasswordProtected = function(padID, callback) +API[">=1"].isPasswordProtected = function(padID, callback) { //ensure this is a group pad if(padID && padID.indexOf("$") == -1) @@ -584,7 +603,7 @@ Example returns: {code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]} {code: 1, message:"padID does not exist", data: null} */ -exports.listAuthorsOfPad = function(padID, callback) +API[">=1"].listAuthorsOfPad = function(padID, callback) { //get the pad getPadSafe(padID, true, function(err, pad) @@ -618,7 +637,7 @@ Example returns: {code: 1, message:"padID does not exist"} */ -exports.sendClientsMessage = function (padID, msg, callback) { +API[">=1.1"].sendClientsMessage = function (padID, msg, callback) { getPadSafe(padID, true, function (err, pad) { if (ERR(err, callback)) { return; @@ -636,7 +655,7 @@ Example returns: {"code":0,"message":"ok","data":null} {"code":4,"message":"no or wrong API Key","data":null} */ -exports.checkToken = function(callback) +API[">=1.2"].checkToken = function(callback) { callback(); } @@ -649,7 +668,7 @@ Example returns: {code: 0, message:"ok", data: {chatHead: 42}} {code: 1, message:"padID does not exist", data: null} */ -exports.getChatHead = function(padID, callback) +API[">=1.2.7"].getChatHead = function(padID, callback) { //get the pad getPadSafe(padID, true, function(err, pad) @@ -667,7 +686,7 @@ Example returns: {"code":0,"message":"ok","data":{"html":"Welcome to Etherpad Lite!

This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!

Get involved with Etherpad at http://etherpad.org
aw

","authors":["a.HKIv23mEbachFYfH",""]}} {"code":4,"message":"no or wrong API Key","data":null} */ -exports.createDiffHTML = function(padID, startRev, endRev, callback){ +API[">=1.2.7"].createDiffHTML = function(padID, startRev, endRev, callback){ //check if rev is a number if(startRev !== undefined && typeof startRev != "number") { @@ -794,3 +813,33 @@ function getPadSafe(padID, shouldExist, text, callback) } }); } + +// cache the API functions for each version +var _CACHE = {}; + +module.exports = function(apiVersion) { + + // Get a proper version x.y.z + var v = apiVersion.split("."); + var apiVersion = [v[0]||'0', v[1]||'0', v[2]||'0'].join("."); + + if (! _CACHE[apiVersion]) { + + _CACHE[apiVersion] = {}; + + // got through each of the semver rules + for(var version in API) { + + // if the rule satisfies the required version + if (semver.satisfies(apiVersion, version)) { + // Add these functions + for (var fn in API[version]) { + _CACHE[apiVersion][fn] = API[version][fn]; + } + } + } + + } + + return _CACHE[apiVersion]; +}; \ No newline at end of file diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js index 9f86277a0..76e504178 100644 --- a/src/node/handler/APIHandler.js +++ b/src/node/handler/APIHandler.js @@ -21,7 +21,6 @@ var ERR = require("async-stacktrace"); var fs = require("fs"); -var api = require("../db/API"); var padManager = require("../db/PadManager"); var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; @@ -326,6 +325,8 @@ function callAPI(apiVersion, functionName, fields, req, res) } }); + var api = require("../db/API")(apiVersion); + //call the api function api[functionName](functionParams[0],functionParams[1],functionParams[2],functionParams[3],functionParams[4]); } diff --git a/src/package.json b/src/package.json index 03df87f9b..64641031b 100644 --- a/src/package.json +++ b/src/package.json @@ -36,7 +36,8 @@ "tinycon" : "0.0.1", "underscore" : "1.3.1", "unorm" : "1.0.0", - "languages4translatewiki" : "0.1.3" + "languages4translatewiki" : "0.1.3", + "semver" : "1.1.3" }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": {