diff --git a/lib/note.js b/lib/note.js
index 671e5383b..cd3816f97 100644
--- a/lib/note.js
+++ b/lib/note.js
@@ -12,7 +12,7 @@ var db = require("./db.js");
 var logger = require("./logger.js");
 
 //permission types
-permissionTypes = ["freely", "editable", "locked"];
+permissionTypes = ["freely", "editable", "locked", "private"];
 
 // create a note model
 var model = mongoose.model('note', {
@@ -126,7 +126,11 @@ function findNote(id, callback) {
     });
 }
 
-function newNote(id, permission, callback) {
+function newNote(id, owner, callback) {
+    var permission = "freely";
+    if (owner && owner != "null") {
+        permission = "editable";
+    }
     var note = new model({
         id: id,
         permission: permission,
diff --git a/lib/ot/editor-socketio-server.js b/lib/ot/editor-socketio-server.js
index 1b2529be5..9e4ddf965 100755
--- a/lib/ot/editor-socketio-server.js
+++ b/lib/ot/editor-socketio-server.js
@@ -43,6 +43,7 @@ EditorSocketIOServer.prototype.addClient = function (socket) {
     socket.on('operation', function (revision, operation, selection) {
         operation = LZString.decompressFromUTF16(operation);
         operation = JSON.parse(operation);
+        socket.origin = 'operation';
         self.mayWrite(socket, function (mayWrite) {
             if (!mayWrite) {
                 console.log("User doesn't have the right to edit.");
@@ -59,6 +60,7 @@ EditorSocketIOServer.prototype.addClient = function (socket) {
         self.onGetOperations(socket, base, head);
     });
     socket.on('selection', function (obj) {
+        socket.origin = 'selection';
         self.mayWrite(socket, function (mayWrite) {
             if (!mayWrite) {
                 console.log("User doesn't have the right to edit.");
@@ -104,6 +106,7 @@ EditorSocketIOServer.prototype.onOperation = function (socket, revision, operati
             'operation', clientId, revision,
             wrappedPrime.wrapped.toJSON(), wrappedPrime.meta
         );
+        //set document is dirty
         this.isDirty = true;
     } catch (exc) {
         logger.error(exc);
diff --git a/lib/realtime.js b/lib/realtime.js
index 484ef12e2..d0db60729 100644
--- a/lib/realtime.js
+++ b/lib/realtime.js
@@ -90,46 +90,10 @@ var updater = setInterval(function () {
         if (note.server.isDirty) {
             if (config.debug)
                 logger.info("updater found dirty note: " + key);
-            Note.findNote(note.id, function (err, _note) {
-                if (err || !_note) return callback(err, null);
-                //mongo update
-                if (note.lastchangeuser && _note.lastchangeuser != note.lastchangeuser) {
-                    var lastchangeuser = note.lastchangeuser;
-                    var lastchangeuserprofile = null;
-                    User.findUser(lastchangeuser, function (err, user) {
-                        if (err) return callback(err, null);
-                        if (user && user.profile) {
-                            var profile = JSON.parse(user.profile);
-                            if (profile) {
-                                lastchangeuserprofile = {
-                                    name: profile.displayName || profile.username,
-                                    photo: User.parsePhotoByProfile(profile)
-                                }
-                                note.lastchangeuser = lastchangeuser;
-                                note.lastchangeuserprofile = lastchangeuserprofile;
-                                Note.updateLastChangeUser(_note, lastchangeuser, function (err, result) {
-                                    if (err) return callback(err, null);
-                                });
-                            }
-                        }
-                    });
-                } else {
-                    note.lastchangeuser = null;
-                    note.lastchangeuserprofile = null;
-                    Note.updateLastChangeUser(_note, null, function (err, result) {
-                        if (err) return callback(err, null);
-                    });
-                }
-                //postgres update
-                var body = note.server.document;
-                var title = Note.getNoteTitle(body);
-                title = LZString.compressToBase64(title);
-                body = LZString.compressToBase64(body);
-                db.saveToDB(key, title, body, function (err, result) {
+            updaterUpdateMongo(note, function(err, result) {
+                if (err) return callback(err, null);
+                updaterUpdatePostgres(note, function(err, result) {
                     if (err) return callback(err, null);
-                    note.server.isDirty = false;
-                    note.updatetime = Date.now();
-                    emitCheck(note);
                     callback(null, null);
                 });
             });
@@ -140,6 +104,56 @@ var updater = setInterval(function () {
         if (err) return logger.error('updater error', err);
     });
 }, 1000);
+function updaterUpdateMongo(note, callback) {
+    Note.findNote(note.id, function (err, _note) {
+        if (err || !_note) return callback(err, null);
+        if (note.lastchangeuser) {
+            if (_note.lastchangeuser != note.lastchangeuser) {
+                var lastchangeuser = note.lastchangeuser;
+                var lastchangeuserprofile = null;
+                User.findUser(lastchangeuser, function (err, user) {
+                    if (err) return callback(err, null);
+                    if (user && user.profile) {
+                        var profile = JSON.parse(user.profile);
+                        if (profile) {
+                            lastchangeuserprofile = {
+                                name: profile.displayName || profile.username,
+                                photo: User.parsePhotoByProfile(profile)
+                            }
+                            _note.lastchangeuser = lastchangeuser;
+                            note.lastchangeuserprofile = lastchangeuserprofile;
+                            Note.updateLastChangeUser(_note, lastchangeuser, function (err, result) {
+                                if (err) return callback(err, null);
+                                callback(null, null);
+                            });
+                        }
+                    }
+                });
+            }
+        } else {
+            _note.lastchangeuser = null;
+            note.lastchangeuserprofile = null;
+            Note.updateLastChangeUser(_note, null, function (err, result) {
+                if (err) return callback(err, null);
+                callback(null, null);
+            });
+        }
+    });
+}
+function updaterUpdatePostgres(note, callback) {
+    //postgres update
+    var body = note.server.document;
+    var title = Note.getNoteTitle(body);
+    title = LZString.compressToBase64(title);
+    body = LZString.compressToBase64(body);
+    db.saveToDB(note.id, title, body, function (err, result) {
+        if (err) return callback(err, null);
+        note.server.isDirty = false;
+        note.updatetime = Date.now();
+        emitCheck(note);
+        callback(null, null);
+    });
+}
 //clean when user not in any rooms or user not in connected list
 var cleaner = setInterval(function () {
     async.each(Object.keys(users), function (key, callback) {
@@ -310,6 +324,19 @@ var disconnectSocketQueue = [];
 
 function finishConnection(socket, note, user) {
     if (!socket || !note || !user) return;
+    //check view permission
+    if (note.permission == 'private') {
+        if (socket.request.user && socket.request.user.logged_in && socket.request.user._id == note.owner) {
+            //na
+        } else {
+            socket.emit('info', {
+                code: 403
+            });
+            clearSocketQueue(connectionSocketQueue, socket);
+            isConnectionBusy = false;
+            return socket.disconnect(true);
+        }
+    }
     note.users[socket.id] = user;
     note.socks.push(socket);
     note.server.addClient(socket);
@@ -363,13 +390,9 @@ function startConnection(socket) {
 
             var owner = data.rows[0].owner;
             var ownerprofile = null;
-            var permission = "freely";
-            if (owner && owner != "null") {
-                permission = "editable";
-            }
 
             //find or new note
-            Note.findOrNewNote(notename, permission, function (err, note) {
+            Note.findOrNewNote(notename, owner, function (err, note) {
                 if (err) {
                     responseError(res, "404", "Not Found", "oops.");
 					clearSocketQueue(connectionSocketQueue, socket);
@@ -399,41 +422,52 @@ function startConnection(socket) {
                     updatetime: moment(updatetime).valueOf(),
                     server: server
                 };
-
-                if (lastchangeuser) {
-                    //find last change user profile if lastchangeuser exists
-                    User.findUser(lastchangeuser, function (err, user) {
-                        if (!err && user && user.profile) {
-                            var profile = JSON.parse(user.profile);
-                            if (profile) {
-                                lastchangeuserprofile = {
-                                    name: profile.displayName || profile.username,
-                                    photo: User.parsePhotoByProfile(profile)
+                
+                async.parallel([
+                    function getlastchangeuser(callback) {
+                        if (lastchangeuser) {
+                            //find last change user profile if lastchangeuser exists
+                            User.findUser(lastchangeuser, function (err, user) {
+                                if (!err && user && user.profile) {
+                                    var profile = JSON.parse(user.profile);
+                                    if (profile) {
+                                        lastchangeuserprofile = {
+                                            name: profile.displayName || profile.username,
+                                            photo: User.parsePhotoByProfile(profile)
+                                        }
+                                        notes[notename].lastchangeuserprofile = lastchangeuserprofile;
+                                    }
                                 }
-                                notes[notename].lastchangeuserprofile = lastchangeuserprofile;
-                            }
+                                callback(null, null);
+                            });
+                        } else {
+                            callback(null, null);
                         }
-                    });
-                }
-
-                if (owner && owner != "null") {
-                    //find owner profile if owner exists
-                    User.findUser(owner, function (err, user) {
-                        if (!err && user && user.profile) {
-                            var profile = JSON.parse(user.profile);
-                            if (profile) {
-                                ownerprofile = {
-                                    name: profile.displayName || profile.username,
-                                    photo: User.parsePhotoByProfile(profile)
+                    },
+                    function getowner(callback) {
+                        if (owner && owner != "null") {
+                            //find owner profile if owner exists
+                            User.findUser(owner, function (err, user) {
+                                if (!err && user && user.profile) {
+                                    var profile = JSON.parse(user.profile);
+                                    if (profile) {
+                                        ownerprofile = {
+                                            name: profile.displayName || profile.username,
+                                            photo: User.parsePhotoByProfile(profile)
+                                        }
+                                        notes[notename].ownerprofile = ownerprofile;
+                                    }
                                 }
-                                notes[notename].ownerprofile = ownerprofile;
-                            }
+                                callback(null, null);
+                            });
+                        } else {
+                            callback(null, null);
                         }
-                        finishConnection(socket, notes[notename], users[socket.id]);
-                    });
-                } else {
+                    }
+                ], function(err, results){
+                    if (err) return;
                     finishConnection(socket, notes[notename], users[socket.id]);
-                }
+                });
             });
         });
     } else {
@@ -545,14 +579,14 @@ function ifMayEdit(socket, callback) {
             if (!socket.request.user || !socket.request.user.logged_in)
                 mayEdit = false;
             break;
-        case "locked":
+        case "locked": case "private":
             //only owner can change
             if (note.owner != socket.request.user._id)
                 mayEdit = false;
             break;
     }
     //if user may edit and this note have owner (not anonymous usage)
-    if (mayEdit && note.owner && note.owner != "null") {
+    if (socket.origin == 'operation' && mayEdit && note.owner && note.owner != "null") {
         //save for the last change user id
 		if (socket.request.user && socket.request.user.logged_in) {
         	note.lastchangeuser = socket.request.user._id;
@@ -652,12 +686,22 @@ function connection(socket) {
                             permission: permission
                         };
                         realtime.io.to(note.id).emit('permission', out);
-                        /*
                         for (var i = 0, l = note.socks.length; i < l; i++) {
                             var sock = note.socks[i];
-                            sock.emit('permission', out);
-                        };
-                        */
+                            if (typeof sock !== 'undefined' && sock) {
+                                //check view permission
+                                if (permission == 'private') {
+                                    if (sock.request.user && sock.request.user.logged_in && sock.request.user._id == note.owner) {
+                                        //na
+                                    } else {
+                                        sock.emit('info', {
+                                            code: 403
+                                        });
+                                        return sock.disconnect(true);
+                                    }
+                                }
+                            }
+                        }
                     });
                 });
             }
diff --git a/lib/response.js b/lib/response.js
index a30df4700..e27411c85 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -90,21 +90,9 @@ function showIndex(req, res, next) {
 }
 
 function responseHackMD(res, noteId) {
-    if (noteId != config.featuresnotename) {
-        if (!Note.checkNoteIdValid(noteId)) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
-        }
-        noteId = LZString.decompressFromBase64(noteId);
-        if (!noteId) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
-        }
-    }
     db.readFromDB(noteId, function (err, data) {
         if (err) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
         var body = LZString.decompressFromBase64(data.rows[0].content);
         var meta = null;
@@ -144,14 +132,18 @@ function newNote(req, res, next) {
     body = LZString.compressToBase64(body);
     var owner = null;
     if (req.isAuthenticated()) {
-        owner = req.session.passport.user;
+        owner = req.user._id;
     }
     db.newToDB(newId, owner, body, function (err, result) {
         if (err) {
-            responseError(res, "500", "Internal Error", "wtf.");
-            return;
+            return response.errorInternalError(res);
         }
-        res.redirect("/" + LZString.compressToBase64(newId));
+        Note.newNote(newId, owner, function(err, result) {
+            if (err) {
+                return response.errorInternalError(res);
+            }
+            res.redirect("/" + LZString.compressToBase64(newId));
+        });
     });
 }
 
@@ -162,8 +154,7 @@ function showFeatures(req, res, next) {
             body = LZString.compressToBase64(body);
             db.newToDB(config.featuresnotename, null, body, function (err, result) {
                 if (err) {
-                    responseError(res, "500", "Internal Error", "wtf.");
-                    return;
+                    return response.errorInternalError(res);
                 }
                 responseHackMD(res, config.featuresnotename);
             });
@@ -175,11 +166,32 @@ function showFeatures(req, res, next) {
 
 function showNote(req, res, next) {
     var noteId = req.params.noteId;
-    if (!Note.checkNoteIdValid(noteId)) {
-        responseError(res, "404", "Not Found", "oops.");
-        return;
+    if (noteId != config.featuresnotename) {
+        if (!Note.checkNoteIdValid(noteId)) {
+            return response.errorNotFound(res);
+        }
+        noteId = LZString.decompressFromBase64(noteId);
+        if (!noteId) {
+            return response.errorNotFound(res);
+        }
     }
-    responseHackMD(res, noteId);
+    Note.findNote(noteId, function (err, note) {
+        if (err || !note) {
+            return response.errorNotFound(res);
+        }
+        db.readFromDB(note.id, function (err, data) {
+            if (err) {
+                return response.errorNotFound(res);
+            }
+            var notedata = data.rows[0];
+            //check view permission
+            if (note.permission == 'private') {
+                if (!req.isAuthenticated() || notedata.owner != req.user._id)
+                    return response.errorForbidden(res);
+            }
+            responseHackMD(res, noteId);
+        });
+    });
 }
 
 function showPublishNote(req, res, next) {
@@ -187,30 +199,33 @@ function showPublishNote(req, res, next) {
     if (shortId.isValid(shortid)) {
         Note.findNote(shortid, function (err, note) {
             if (err || !note) {
-                responseError(res, "404", "Not Found", "oops.");
-                return;
+                return response.errorNotFound(res);
             }
-            //increase note viewcount
-            Note.increaseViewCount(note, function (err, note) {
-                if (err || !note) {
-                    responseError(res, "404", "Not Found", "oops.");
-                    return;
+            db.readFromDB(note.id, function (err, data) {
+                if (err) {
+                    return response.errorNotFound(res);
                 }
-                db.readFromDB(note.id, function (err, data) {
-                    if (err) {
-                        responseError(res, "404", "Not Found", "oops.");
-                        return;
+                var notedata = data.rows[0];
+                //check view permission
+                if (note.permission == 'private') {
+                    if (!req.isAuthenticated() || notedata.owner != req.user._id)
+                        return response.errorForbidden(res);
+                }
+                //increase note viewcount
+                Note.increaseViewCount(note, function (err, note) {
+                    if (err || !note) {
+                        return response.errorNotFound(res);
                     }
-                    var body = LZString.decompressFromBase64(data.rows[0].content);
+                    var body = LZString.decompressFromBase64(notedata.content);
                     var meta = null;
                     try {
                         meta = metaMarked(body).meta;
                     } catch(err) {
                         //na
                     }
-                    var updatetime = data.rows[0].update_time;
+                    var updatetime = notedata.update_time;
                     var text = S(body).escapeHTML().s;
-                    var title = data.rows[0].title;
+                    var title = notedata.title;
                     var decodedTitle = LZString.decompressFromBase64(title);
                     if (decodedTitle) title = decodedTitle;
                     title = Note.generateWebTitle(title);
@@ -247,7 +262,7 @@ function showPublishNote(req, res, next) {
             });
         });
     } else {
-        responseError(res, "404", "Not Found", "oops.");
+        return response.errorNotFound(res);
     }
 }
 
@@ -271,18 +286,12 @@ function renderPublish(data, res) {
 function actionPublish(req, res, noteId) {
     db.readFromDB(noteId, function (err, data) {
         if (err) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
         var owner = data.rows[0].owner;
-        var permission = "freely";
-        if (owner && owner != "null") {
-            permission = "editable";
-        }
-        Note.findOrNewNote(noteId, permission, function (err, note) {
+        Note.findOrNewNote(noteId, owner, function (err, note) {
             if (err) {
-                responseError(res, "404", "Not Found", "oops.");
-                return;
+                return response.errorNotFound(res);
             }
             res.redirect("/s/" + note.shortid);
         });
@@ -292,18 +301,12 @@ function actionPublish(req, res, noteId) {
 function actionSlide(req, res, noteId) {
     db.readFromDB(noteId, function (err, data) {
         if (err) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
         var owner = data.rows[0].owner;
-        var permission = "freely";
-        if (owner && owner != "null") {
-            permission = "editable";
-        }
-        Note.findOrNewNote(noteId, permission, function (err, note) {
+        Note.findOrNewNote(noteId, owner, function (err, note) {
             if (err) {
-                responseError(res, "404", "Not Found", "oops.");
-                return;
+                return response.errorNotFound(res);
             }
             res.redirect("/p/" + note.shortid);
         });
@@ -313,8 +316,7 @@ function actionSlide(req, res, noteId) {
 function actionDownload(req, res, noteId) {
     db.readFromDB(noteId, function (err, data) {
         if (err) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
         var body = LZString.decompressFromBase64(data.rows[0].content);
         var title = Note.getNoteTitle(body);
@@ -331,8 +333,7 @@ function actionDownload(req, res, noteId) {
 function actionPDF(req, res, noteId) {
     db.readFromDB(noteId, function (err, data) {
         if (err) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
         var body = LZString.decompressFromBase64(data.rows[0].content);
         try {
@@ -365,57 +366,81 @@ function noteActions(req, res, next) {
     var noteId = req.params.noteId;
     if (noteId != config.featuresnotename) {
         if (!Note.checkNoteIdValid(noteId)) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
         noteId = LZString.decompressFromBase64(noteId);
         if (!noteId) {
-            responseError(res, "404", "Not Found", "oops.");
-            return;
+            return response.errorNotFound(res);
         }
     }
-    var action = req.params.action;
-    switch (action) {
-    case "publish":
-    case "pretty": //pretty deprecated
-        actionPublish(req, res, noteId);
-        break;
-    case "slide":
-        actionSlide(req, res, noteId);
-        break;
-    case "download":
-        actionDownload(req, res, noteId);
-        break;
-    case "pdf":
-        actionPDF(req, res, noteId);
-        break;
-    default:
-        if (noteId != config.featuresnotename)
-            res.redirect('/' + LZString.compressToBase64(noteId));
-        else
-            res.redirect('/' + noteId);
-        break;
-    }
+    Note.findNote(noteId, function (err, note) {
+        if (err || !note) {
+            return response.errorNotFound(res);
+        }
+        db.readFromDB(note.id, function (err, data) {
+            if (err) {
+                return response.errorNotFound(res);
+            }
+            var notedata = data.rows[0];
+            //check view permission
+            if (note.permission == 'private') {
+                if (!req.isAuthenticated() || notedata.owner != req.user._id)
+                    return response.errorForbidden(res);
+            }
+            var action = req.params.action;
+            switch (action) {
+            case "publish":
+            case "pretty": //pretty deprecated
+                actionPublish(req, res, noteId);
+                break;
+            case "slide":
+                actionSlide(req, res, noteId);
+                break;
+            case "download":
+                actionDownload(req, res, noteId);
+                break;
+            case "pdf":
+                actionPDF(req, res, noteId);
+                break;
+            default:
+                if (noteId != config.featuresnotename)
+                    res.redirect('/' + LZString.compressToBase64(noteId));
+                else
+                    res.redirect('/' + noteId);
+                break;
+            }
+        });
+    });
 }
 
 function publishNoteActions(req, res, next) {
-    var action = req.params.action;
-    switch (action) {
-    case "edit":
-        var shortid = req.params.shortid;
-        if (shortId.isValid(shortid)) {
-            Note.findNote(shortid, function (err, note) {
-                if (err || !note) {
-                    responseError(res, "404", "Not Found", "oops.");
-                    return;
+    var shortid = req.params.shortid;
+    if (shortId.isValid(shortid)) {
+        Note.findNote(shortid, function (err, note) {
+            if (err || !note) {
+                return response.errorNotFound(res);
+            }
+            db.readFromDB(note.id, function (err, data) {
+                if (err) {
+                    return response.errorNotFound(res);
+                }
+                var notedata = data.rows[0];
+                //check view permission
+                if (note.permission == 'private') {
+                    if (!req.isAuthenticated() || notedata.owner != req.user._id)
+                        return response.errorForbidden(res);
+                }
+                var action = req.params.action;
+                switch (action) {
+                case "edit":
+                    if (note.id != config.featuresnotename)
+                        res.redirect('/' + LZString.compressToBase64(note.id));
+                    else
+                        res.redirect('/' + note.id);
+                    break;
                 }
-                if (note.id != config.featuresnotename)
-                    res.redirect('/' + LZString.compressToBase64(note.id));
-                else
-                    res.redirect('/' + note.id);
             });
-        }
-        break;
+        });
     }
 }
 
@@ -424,27 +449,30 @@ function showPublishSlide(req, res, next) {
     if (shortId.isValid(shortid)) {
         Note.findNote(shortid, function (err, note) {
             if (err || !note) {
-                responseError(res, "404", "Not Found", "oops.");
-                return;
+                return response.errorNotFound(res);
             }
-            //increase note viewcount
-            Note.increaseViewCount(note, function (err, note) {
-                if (err || !note) {
-                    responseError(res, "404", "Not Found", "oops.");
-                    return;
+            db.readFromDB(note.id, function (err, data) {
+                if (err) {
+                    return response.errorNotFound(res);
                 }
-                db.readFromDB(note.id, function (err, data) {
-                    if (err) {
-                        responseError(res, "404", "Not Found", "oops.");
-                        return;
+                var notedata = data.rows[0];
+                //check view permission
+                if (note.permission == 'private') {
+                    if (!req.isAuthenticated() || notedata.owner != req.user._id)
+                        return response.errorForbidden(res);
+                }
+                //increase note viewcount
+                Note.increaseViewCount(note, function (err, note) {
+                    if (err || !note) {
+                        return response.errorNotFound(res);
                     }
-                    var body = LZString.decompressFromBase64(data.rows[0].content);
+                    var body = LZString.decompressFromBase64(notedata.content);
                     try {
                         body = metaMarked(body).markdown;
                     } catch(err) {
                         //na
                     }
-                    var title = data.rows[0].title;
+                    var title = notedata.title;
                     var decodedTitle = LZString.decompressFromBase64(title);
                     if (decodedTitle) title = decodedTitle;
                     title = Note.generateWebTitle(title);
@@ -454,7 +482,7 @@ function showPublishSlide(req, res, next) {
             });
         });
     } else {
-        responseError(res, "404", "Not Found", "oops.");
+        return response.errorNotFound(res);
     }
 }
 
diff --git a/public/js/index.js b/public/js/index.js
index 1dfadc9af..86771fde0 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -327,7 +327,8 @@ var ui = {
             label: $(".ui-permission-label"),
             freely: $(".ui-permission-freely"),
             editable: $(".ui-permission-editable"),
-            locked: $(".ui-permission-locked")
+            locked: $(".ui-permission-locked"),
+            private: $(".ui-permission-private")
         }
     },
     toc: {
@@ -1067,6 +1068,10 @@ ui.infobar.permission.editable.click(function () {
 ui.infobar.permission.locked.click(function () {
     emitPermission("locked");
 });
+//private
+ui.infobar.permission.private.click(function () {
+    emitPermission("private");
+});
 
 function emitPermission(_permission) {
     if (_permission != permission) {
@@ -1094,6 +1099,10 @@ function updatePermission(newPermission) {
         label = '<i class="fa fa-lock"></i> Locked';
         title = "Only owner can edit";
         break;
+    case "private":
+        label = '<i class="fa fa-hand-stop-o"></i> Private';
+        title = "Only owner can view & edit";
+        break;
     }
     if (personalInfo.userid == owner) {
         label += ' <i class="fa fa-caret-down"></i>';
@@ -1118,6 +1127,7 @@ function havePermission() {
         }
         break;
     case "locked":
+    case "private":
         if (personalInfo.userid != owner) {
             bool = false;
         } else {
@@ -1145,7 +1155,14 @@ socket.emit = function () {
 };
 socket.on('info', function (data) {
     console.error(data);
-    location.href = "./404";
+    switch (data.code) {
+    case 404:
+        location.href = "./404";
+        break;
+    case 403:
+        location.href = "./403";
+        break;
+    }
 });
 socket.on('error', function (data) {
     console.error(data);
@@ -1755,6 +1772,7 @@ editor.on('beforeChange', function (cm, change) {
                 $('.signin-modal').modal('show');
                 break;
             case "locked":
+            case "private":
                 $('.locked-modal').modal('show');
                 break;
             }
diff --git a/public/views/body.ejs b/public/views/body.ejs
index b3a49db8a..fa7436e7f 100644
--- a/public/views/body.ejs
+++ b/public/views/body.ejs
@@ -18,6 +18,7 @@
                         <li class="ui-permission-freely"><a><i class="fa fa-leaf fa-fw"></i> Freely - Anyone can edit</a></li>
                         <li class="ui-permission-editable"><a><i class="fa fa-shield fa-fw"></i> Editable - Signed people can edit</a></li>
                         <li class="ui-permission-locked"><a><i class="fa fa-lock fa-fw"></i> Locked - Only owner can edit</a></li>
+                        <li class="ui-permission-private"><a><i class="fa fa-hand-stop-o fa-fw"></i> Private - Only owner can view &amp; edit</a></li>
                     </ul>
                 </span>
             </small>