view backends/directory.js @ 55:fd69d35cf2e6

Move default storage directory; better naming of nodes; fix notification sending.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 25 Jul 2011 17:35:32 -0700
parents 023f767662d3
children 99bd1d1ac071
line wrap: on
line source

/*
 *  Copyright (C) 2010  Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
 *
 *  This file is part of PSĜS, a PubSub server written in JavaScript.
 *
 *  PSĜS is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License.
 *
 *  PSĜS is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with PSĜS.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

var fs = require('fs');
var Node = require('../nodes').Node;
var backend = exports;

backend.save = function(dir) {
	if (!dir)
		dir = 'data';

	fs.stat(dir, function(err, stats) {
		if (err)
			fs.mkdir(dir, 509); // 0755 in decimal
		else if (!stats.isDirectory()) {
			console.log('\x1b[1;41mThe file “' + dir + '” isn’t a directory. Exiting.\x1b[0m');
			process.exit(1);
		}

		fs.readdir(dir, function(err, files) {
			function sanitize(o) {
				var n = {};
				for (var i in o) {
					if (i == 'content' || o[i].setFromISO8601)
						n[i] = o[i].toString();
					else if (o[i] instanceof Array)
						n[i] = o[i];
					else if (typeof o[i] == 'object')
						n[i] = sanitize(o[i]);
					else if (typeof o[i] == 'function')
						;
					else
						n[i] = o[i];
				}
				return n;
			}
			var data = sanitize(backend.list);

			var inspect = require('sys').inspect;

			for (var nodeID in data)
				fs.writeFile(dir+'/'+encodeURI(nodeID).replace('/', '%2f')+'.json', inspect(data[nodeID], false, null));

			var toDelete = [];

			for (var i in files) {
				var file = files[i];
				if (!(file.replace(/\.json$/, '') in data))
					toDelete.push(file);
			}

			for (var nodeID in toDelete)
				fs.unlink(dir+'/'+encodeURI(toDelete[nodeID]).replace('/', '%2f'));
		});
	});
}

backend.load = function(dir) {
	if (!dir)
		dir = 'data';

	fs.stat(dir, function(err, stats) {
		if (err)
			fs.mkdir(dir, 509); // 0755 in decimal
		else if (!stats.isDirectory()) {
			console.log('\x1b[1;41mThe file “' + dir + '” isn’t a directory. Exiting.\x1b[0m');
			process.exit(1);
		}

		fs.readdir(dir, function(err, files) {
			var xmpp = require('xmpp');
			function parseStanza(path, content) {
				var stanza = null;
				var stream = new xmpp.Stream({
					stanza: function (stanza) {
						path[content] = stanza;
					}
				});
				stream.opened = true;
				stream.data(path[content]);
			}

			function endParsing(o) {
				var regexp = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ/;
				for (var i in o) {
					if (typeof o[i] == 'string' && i == 'content')
						parseStanza(o, i);
					else if (typeof o[i] == 'string' && regexp(o[i])) {
						var today = new Date();
						today.setFromISO8601(o[i]);
						o[i] = today;
					} else if (typeof o[i] == 'object')
						endParsing(o[i]);
				}
				return o;
			}

			backend.list = {};

			for (var i in files) {
				var file = files[i];
				if (/^\./.test(file))
					continue;

				var nodeID = decodeURI(file.replace(/\.json$/, '').replace('%2f', '/'));

				var data = fs.readFileSync(dir+'/'+file).toString();

				var obj = eval('('+data+')');
				backend.list[nodeID] = endParsing(obj);

				for (var j in Node.prototype)
					backend.list[nodeID][j] = Node.prototype[j];
			}
		});
	});
}