bigbluebutton-Github/labs/bbb-html5-client/routes/index.js
2012-10-20 14:18:39 -05:00

260 lines
12 KiB
JavaScript
Executable File

/**
* This returns the folder where the presentation files will be
* stored for that particular presentationID.
* @param {string} presentationID the presentationID being looked up for a folder
* @return {string} the relative URL for where the images will be stored
*/
//exports.presentationImageFolder = function(presentationID) {
//return 'public/images/presentation' + presentationID;
//return 'public/images/presentations/'+presentationID;
//};
exports.presentationImageFolder = function(meetingID,presentationID) {
return '/var/bigbluebutton/' + meetingID + "/" + meetingID + "/" + presentationID + "/pngs";
};
/**
* When requesting the homepage a potential meetingID and sessionIDare extracted
* from the user's cookie. If they match with a user that is in the databaseunder
* the same data, they are instantly redirected to join into the meeting.
* If they are not, they will be redirected to the index page where they can enter
* their login details.
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.get_index = function(req, res) {
redisAction.isValidSession(req.cookies.meetingid, req.cookies.sessionid, function (reply) {
if(!reply) {
redisAction.getMeetings(function (meetings){
res.render('index', { title: 'BigBlueButton HTML5 Client', max_u: max_username_length, meetings: meetings });
});
}
else {
res.redirect('/chat');
}
});
};
/**
* Given a meetingID, sessionID and username a meeting will be created
* and a user with the username will be joined.The callback returns either true or false depending on whether
* the meeting was created successfully or not.
* @param {string} meetingID the meeting ID of the meeting we are creating and/or connecting to
* @param {string} sessionID the session ID of the user that is connecting to the meeting
* @param {string} username username of the users that that is connecting to the meeting
* @param {Function} callback the callback function returns true if meeting successfully started and joined, false otherwise
* @return {undefined} callback is used to send the status back to the caller of this function
*/
function makeMeeting(meetingID, sessionID, username, callback) {
if((username) && (meetingID) && (username.length <= max_username_length) && (meetingID.split(' ').length == 1)) {
var publicID = (new Date()).getTime();
redisAction.isMeetingRunning(meetingID, function(isRunning) {
if(!isRunning) {
redisAction.createMeeting(meetingID, function() {
redisAction.setCurrentTool(meetingID, 'line');
redisAction.setPresenter(meetingID, sessionID, publicID);
});
}
});
redisAction.createUser(meetingID, sessionID);
store.get(redisAction.getCurrentPresentationString(meetingID), function (err, currPresID) {
if(!currPresID) {
redisAction.createPresentation(meetingID, true, function (presentationID) {
redisAction.createPage(meetingID, presentationID, 'default.png', true, function (pageID) {
redisAction.setViewBox(meetingID, JSON.stringify([0, 0, 1, 1]));
var folder = routes.presentationImageFolder(meetingID,presentationID);
fs.mkdir(folder, 0777 , function (reply) {
newFile = fs.createWriteStream(folder + '/default.png');
oldFile = fs.createReadStream('images/default.png');
newFile.once('open', function (fd) {
util.pump(oldFile, newFile);
redisAction.setImageSize(meetingID, presentationID, pageID, 800, 600);
});
});
});
});
}
});
redisAction.setIDs(meetingID, sessionID, publicID, function() {
redisAction.updateUserProperties(meetingID, sessionID, ["username", username,
"meetingID", meetingID, "refreshing", false, "dupSess", false, "sockets", 0, 'pubID', publicID]);
callback(true);
});
}
else callback(false);
}
/**
* Upon submitting their login details from the index page via a POST request,
* a meeting will be created and joined. If an error occurs, which usually
* results in using a username/meetingID that is too long, they will be redirected
* to the index page again.
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.post_index = function(req, res) {
var username = sanitizer.escape(req.body.user.name);
var meetingID = sanitizer.escape(req.body.meeting.id);
var sessionID = req.sessionID;
makeMeeting(meetingID, sessionID, username, function(join) {
if(join) {
res.cookie('sessionid', sessionID); //save the id so socketio can get the username
res.cookie('meetingid', meetingID);
res.redirect('/chat');
}
else res.redirect('/');
});
};
/**
* When a user logs out, their session is destroyed,
* and their cookies are cleared.
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.logout = function(req, res) {
req.session.destroy(); //end the session
res.cookie('sessionid', null); //clear the cookie from the client
res.cookie('meetingid', null);
};
/**
* The join URL is used to connect to a meeting immediately without
* going to the login screen.
* Example:
* localhost:3000/join?meetingid=123&fullname=Ryan&checksum=password
* This will connect under the meetingID 123 with the name "Ryan" as
* long as the checksum string is equal on the server side.
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.join = function(req, res) {
var query = req.query;
if(query) {
var meetingID = query.meetingid;
var username = query.fullname;
var checksum = query.checksum;
var sessionID = req.sessionID;
// checksum is checked here against a simple keyword for now
if(checksum == "password") {
//create meeting
makeMeeting(meetingID, sessionID, username, function(join) {
//if the meeting was created successfully
if(join) {
//store the cookies
res.cookie('sessionid', sessionID); //save the id so socketio can get the username
res.cookie('meetingid', meetingID);
res.redirect('/chat');
}
else res.redirect('/');
});
}
else res.redirect('/');
}
};
/**
* When we return to the chat page (or open a new tab when already logged in)
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.get_chat = function(req, res) {
//requiresLogin before this verifies that a user is logged in...
var meetingID = req.cookies.meetingid;
redisAction.getUserProperty(meetingID, req.cookies.sessionid, "username", function (username) {
res.render('chat', { title: 'BigBlueButton HTML5 Client', user: username, max_chat_length: max_chat_length, meetingID : meetingID });
});
};
/**
* POSTing a file from the client page, the images will be
* converted and their URLs will be send via SocketIO if
* successful. If unsuccessful, a status of failed will be sent.
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.post_chat = function(req, res) {
// the client must send a file
if(req.files.image.size !== 0) {
var meetingID = req.cookies.meetingid;
var sessionID = req.cookies.sessionid;
pub.publish(meetingID, JSON.stringify(['uploadStatus', "Processing..."]));
redisAction.isValidSession(meetingID, sessionID, function (reply) {
var file = req.files.image.path;
var pageIDs = [];
redisAction.getCurrentPresentationID(meetingID, function(prevPresID) {
redisAction.getCurrentPageID(meetingID, prevPresID, function(prevPageID) {
redisAction.createPresentation(meetingID, false, function (presentationID) {
redisAction.setViewBox(meetingID, JSON.stringify([0, 0, 1, 1]));
var folder = routes.presentationImageFolder(meetingID,presentationID);
//make the directory the presentation files will go into.
fs.mkdir(folder, 0777 , function (reply) {
// ImageMagick call to convert file to PNG images named slide0.png, slide1.png, slide2.png, etc...
im.convert(['-quality', '50', '-density', '150x150', file, folder + '/slide%d.png'], function (err) {
if(!err) {
//counts how many files are in the folder for the presentation to get the slide count.
exec("ls -1 " + folder + "/ | wc -l", function (error, stdout, stdouterr) {
var numOfPages = parseInt(stdout, 10);
var numComplete = 0;
// interate through each of the files and create a page for each of them.
for(var i = 0; i < numOfPages; i++) {
var setCurrent = true;
if(i !== 0) setCurrent = false;
redisAction.createPage(meetingID, presentationID, "slide" + i + ".png", setCurrent, function (pageID, imageName) {
//ImageMagick call to get the image size from each of the converted images.
im.identify(folder + "/" + imageName, function(err, features) {
if (err) throw err;
else redisAction.setImageSize(meetingID, presentationID, pageID, features.width, features.height, function() {
pageIDs.push(pageID);
numComplete++;
if(numComplete == numOfPages) {
// Once complete, set the current presentation to the new one
// and publish the new slides to all members of the meeting.
redisAction.setCurrentPresentation(meetingID, presentationID, function() {
pub.publish(meetingID, JSON.stringify(['clrPaper']));
socketAction.publishSlides(meetingID, null, function() {
socketAction.publishViewBox(meetingID);
pub.publish(meetingID, JSON.stringify(['uploadStatus', "Upload succeeded", true]));
});
});
}
});
});
});
}
});
}
else {
console.log(err);
fs.rmdir(folder, function() {
console.log("Deleted invalid presentation folder");
pub.publish(meetingID, JSON.stringify(['uploadStatus', "Invalid file", true]));
});
}
});
});
});
});
});
});
}
res.redirect('/chat');
};
/**
* Any other page that we have not defined yet.
* @param {Object} req Request object from the client
* @param {Object} res Response object to the client
* @return {undefined} Response object is sent back to the client.
*/
exports.error404 = function(req, res) {
console.log("User tried to access: " + req.url);
res.send("Page not found", 404);
};