Example #1
0
        public CheckFileInfoResponse InitializeValidatorParams(string file_id, string access_token, string access_token_ttl)
        {
            var documentId = Convert.ToInt64(file_id);
            var document   = FB.GetDocument(documentId);

            BaseFileName     = "document.wopitest";
            OwnerId          = "1";
            Size             = document.BinaryData.Length;
            UserId           = "1";
            Version          = "1.0";
            UserFriendlyName = "Lloyd";
            UserInfo         = JsonConvert.SerializeObject(new { userName = "******", userId = 1 });

            //SupportedShareUrlTypes = new string[] { "ReadWrite" }; //  is another option

            ReadOnly = false;
            RestrictedWebViewOnly = false;
            // UserCanAttend = true;
            //UserCanPresent = true;
            UserCanNotWriteRelative = false;
            UserCanRename           = true;
            UserCanWrite            = true;

            SupportsUpdate             = true;
            SupportsLocks              = true;
            SupportsExtendedLockLength = true;
            SupportsGetLock            = true;
            SupportsRename             = true;
            SupportsUserInfo           = true;
            SupportsDeleteFile         = true;

            IsAnonymousUser = false;
            return(this);
        }
Example #2
0
 public ActionResult EditPowerpoint(long id) //701
 {
     return(View("WopiFrame", new EditDocumentModel()
     {
         AccessToken = FB.GetAccessToken(id),
         AccessTokenExpires = GetTokenExpires(),
         ActionUrl = GetEditPowerpointUrl(id)
     }));
 }
Example #3
0
        public static bool IsLockMismatch(HttpRequestBase request, FileBound.Document document, out string currentLock)
        {
            var lockInfo        = FB.GetLockInfo(document);
            var currentLockInfo = !string.IsNullOrEmpty(lockInfo)
                                ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(lockInfo)
                                : null;

            currentLock = currentLockInfo?.Lock ?? string.Empty;
            return(currentLockInfo != null && (currentLockInfo.Lock != request.Headers[WopiHeaders.Lock]));
        }
Example #4
0
        public WopiResponse HandleRefresh()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var documentId  = Convert.ToInt64(requestData.Id);
            var document    = FB.GetDocument(documentId);

            if (document == null)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                });
            }

            var newLock = new LockInfo()
            {
                DateCreated = DateTime.UtcNow, Lock = _request.Headers[WopiHeaders.Lock]
            };

            var currentLockInfo = FB.GetLockInfo(document);
            var currentLock     = !string.IsNullOrEmpty(currentLockInfo)
                ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(currentLockInfo)
                : null;

            if (currentLock == null)
            {
                // on refresh, there should already be a lock
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.LockMismatch, Message = ""
                });
            }

            lock (currentLock)
            {
                if (currentLock.Lock != newLock.Lock)
                {
                    // trying to lock again with a different lock? YEAH RIGHT
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                    });
                }

                // update the lock (refresh) and return success:
                FB.UpdateLockInfo(document, Newtonsoft.Json.JsonConvert.SerializeObject(newLock));
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.Success
                });
            }
        }
        // required endpoints:
        // https://wopi.readthedocs.io/en/latest/wopi_requirements.html#requirements

        protected override void OnActionExecuting(ActionExecutingContext context)
        {
            var requestData = WopiRequest.ParseRequest(Request);

            if (!FB.ValidateAccessToken(Request.QueryString["access_token"], Convert.ToInt64(requestData.Id)))
            {
                HandleResponse(new WopiResponse()
                {
                    ResponseType = WopiResponseType.InvalidToken, Message = "Invalid Token"
                });
                context.Result = new HttpStatusCodeResult(Response.StatusCode, Response.StatusDescription);
            }

            base.OnActionExecuting(context);
        }
Example #6
0
        public ActionResult Index(long id)
        {
            // discovery xml:
            // https://onenote.officeapps-df.live.com/hosting/discovery
            // action url for Edit Docx:
            //var actionUrl = "https://word-edit.officeapps-df.live.com/we/wordeditorframe.aspx?<ui=UI_LLCC&><rs=DC_LLCC&><dchat=DISABLE_CHAT&><hid=HOST_SESSION_ID&><showpagestats=PERFSTATS&><IsLicensedUser=BUSINESS_USER&>";

            var tokenExpires = Convert.ToInt64(DateTime.UtcNow.AddDays(1).ToUniversalTime().Subtract(
                                                   new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
                                                   ).TotalMilliseconds);

            return(View("WopiFrame", new EditDocumentModel()
            {
                AccessToken = FB.GetAccessToken(id),
                AccessTokenExpires = tokenExpires,
                ActionUrl = GetValidatorUrl(id)
            }));
        }
Example #7
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);

            try
            {
                var documentId = Convert.ToInt64(requestData.Id);
                FB.DeleteDocument(documentId);
            }
            catch (Exception ex)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.ServerError, Message = ex.Message
                });
            }

            return(new WopiResponse()
            {
                ResponseType = WopiResponseType.Success
            });
        }
Example #8
0
        public WopiJsonResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);

            var responseData = new PutRelativeResponse();

            var documentId      = Convert.ToInt64(requestData.Id);
            var relativeTarget  = _request.Headers[WopiHeaders.RelativeTarget];
            var suggestedTarget = _request.Headers[WopiHeaders.SuggestedTarget];

            // make sure we don't have both headers present:
            if (!string.IsNullOrEmpty(relativeTarget) && !string.IsNullOrEmpty(suggestedTarget))
            {
                return(new WopiJsonResponse()
                {
                    StatusCode = 501,
                    Json = new PutRelativeResponse()
                });
            }

            var    overwriteRelative = _request.Headers[WopiHeaders.OverwriteRelativeTarget];
            string extension;

            if (!string.IsNullOrEmpty(relativeTarget))
            {
                // check if we have a file matching the target name
                // and if so, return 409 conflict w/ lock response
                extension         = relativeTarget.Substring(relativeTarget.LastIndexOf(".") + 1);
                responseData.Name = IOHelper.Utf7Encode(relativeTarget); // extension should already be here, we just need to get it for below

                var overwriteExisting = !string.IsNullOrEmpty(overwriteRelative) && overwriteRelative.ToLower().Equals("true");
                var relativeDocument  = FB.GetDocumentByNameAndExtension(responseData.Name, extension, documentId);

                // does this document already exist?
                if (relativeDocument != null)
                {
                    // lock check - make sure the existing document isn't locked:
                    var currentLock = "";
                    if (LockHelper.IsLockMismatch(_request, relativeDocument, out currentLock))
                    {
                        return(new WopiJsonResponse()
                        {
                            StatusCode = 409, Json = responseData
                        });
                    }

                    // not locked - but the document exists, so make sure the overwrite existing header is set:
                    if (!overwriteExisting)
                    {
                        return(new WopiJsonResponse()
                        {
                            StatusCode = 409,
                            Json = responseData
                        });
                    }
                }
            }
            else
            {
                // suggested mode:
                // save the file with whatever name we want, and return that name:
                extension         = suggestedTarget.Substring(suggestedTarget.LastIndexOf(".") + 1);
                responseData.Name = "wopitest_putrelative." + extension;
            }

            var binary        = IOHelper.StreamToBytes(_request.InputStream);
            var newDocumentId = FB.SaveNewDocument(binary, extension, responseData.Name, documentId);
            var newToken      = FB.GetAccessToken(newDocumentId);

            responseData.Url = $"{Constants.WopiApiUrl}wopi/files/{newDocumentId}?access_token={newToken}";

            return(new WopiJsonResponse()
            {
                StatusCode = 200,
                Json = responseData
            });
        }
        public FileContentResult GetFile(long file_id, string access_token, string access_token_ttl)
        {
            var document = FB.GetDocument(file_id);

            return(File(document.BinaryData, FB.GetContentType(document.Extension)));
        }
Example #10
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);

            try
            {
                var documentId = Convert.ToInt64(requestData.Id);
                var document   = FB.GetDocument(documentId);

                if (document == null)
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                    });
                }

                var currentLock = "";
                if (LockHelper.IsLockMismatch(_request, document, out currentLock))
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch, Message = currentLock
                    });
                }

                // FileInfo putTargetFileInfo = new FileInfo(requestData.FullPath);

                // The WOPI spec allows for a PutFile to succeed on a non-locked file if the file is currently zero bytes in length.
                // This allows for a more efficient Create New File flow that saves the Lock roundtrips.
                //if (!hasExistingLock && putTargetFileInfo.Length != 0)
                //{
                //    // With no lock and a non-zero file, a PutFile could potentially result in data loss by clobbering
                //    // existing content.  Therefore, return a lock mismatch error.
                //    ReturnLockMismatch(context.Response, reason: "PutFile on unlocked file with current size != 0");
                //}

                // Either the file has a valid lock that matches the lock in the request, or the file is unlocked
                // and is zero bytes.  Either way, proceed with the PutFile.

                var binary = IOHelper.StreamToBytes(_request.InputStream);
                FB.SaveDocument(document, binary);
            }
            catch (UnauthorizedAccessException uex)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.FileUnknown, Message = uex.Message
                });
            }
            catch (Exception ex)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.ServerError, Message = ex.Message
                });
            }

            return(new WopiResponse()
            {
                ResponseType = WopiResponseType.Success
            });
        }
Example #11
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var documentId  = Convert.ToInt64(requestData.Id);
            var document    = FB.GetDocument(documentId);

            if (document == null)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                });
            }

            var newLock = new LockInfo()
            {
                DateCreated = DateTime.UtcNow, Lock = _request.Headers[WopiHeaders.Lock]
            };
            var oldLock = _request.Headers[WopiHeaders.OldLock];

            var currentLockInfo = FB.GetLockInfo(document);
            var currentLock     = !string.IsNullOrEmpty(currentLockInfo)
                ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(currentLockInfo)
                : null;

            if (currentLock == null)
            {
                // The file is not currently locked or the lock has already expired
                FB.UpdateLockInfo(document, Newtonsoft.Json.JsonConvert.SerializeObject(newLock));
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.Success
                });
            }

            lock (currentLock)
            {
                // unlock & relock:
                if (!string.IsNullOrEmpty(oldLock))
                {
                    if (oldLock == currentLock.Lock && oldLock != newLock.Lock)
                    {
                        FB.UpdateLockInfo(document, Newtonsoft.Json.JsonConvert.SerializeObject(newLock));
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.Success
                        });
                    }

                    if (oldLock != currentLock.Lock)
                    {
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                        });
                    }
                }

                if (currentLock.Lock != newLock.Lock)
                {
                    // trying to lock again with a different lock? YEAH RIGHT
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                    });
                }

                // locking with the same lock? validator says this should be ok:
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.Success
                });
            }
        }
Example #12
0
        public WopiJsonResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var newName     = _request.Headers[WopiHeaders.RequestedName];

            try
            {
                // if the file name is illegal then
                // return 400
                // add response header WopiHeaders.InvalidFileNameError - describing the reason the rename operation could not be completed
                if (string.IsNullOrEmpty(newName))
                {
                    return(new WopiJsonResponse()
                    {
                        StatusCode = 400,
                        Headers = new NameValueCollection {
                            { WopiHeaders.InvalidFileNameError, "Invalid filename for rename" }
                        },
                    });
                }

                newName = IOHelper.Utf7Encode(newName);

                var documentId = Convert.ToInt64(requestData.Id);
                var document   = FB.GetDocument(documentId);

                if (document == null)
                {
                    return(new WopiJsonResponse()
                    {
                        StatusCode = 404, Json = new RenameResponse()
                    });
                }

                var currentLock = "";
                if (LockHelper.IsLockMismatch(_request, document, out currentLock))
                {
                    return(new WopiJsonResponse()
                    {
                        StatusCode = 409, Json = new RenameResponse()
                    });
                }

                // rename the document:
                FB.RenameDocument(document, newName);
            }
            catch (Exception ex)
            {
                //return new WopiResponse() { ResponseType = WopiResponseType.ServerError, Message = ex.Message };
                return(new WopiJsonResponse()
                {
                    StatusCode = 500, Json = new { Message = ex.Message }
                });
            }

            //return new WopiResponse() { ResponseType = WopiResponseType.Success };
            return(new WopiJsonResponse()
            {
                StatusCode = 200, Json = new RenameResponse()
                {
                    Name = newName
                }
            });
        }
Example #13
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var documentId  = Convert.ToInt64(requestData.Id);
            var document    = FB.GetDocument(documentId);

            try
            {
                if (document == null)
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                    });
                }

                var newLock = _request.Headers[WopiHeaders.Lock];

                var currentLockInfo = FB.GetLockInfo(document);
                var currentLock     = !string.IsNullOrEmpty(currentLockInfo)
                    ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(currentLockInfo)
                    : null;

                if (currentLock == null)
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch
                    });
                }

                lock (currentLock)
                {
                    if (currentLock.Lock == newLock)
                    {
                        // There is a valid lock on the file and the existing lock matches the provided one
                        FB.UpdateLockInfo(document, string.Empty);
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.Success
                        });
                    }
                    else
                    {
                        // The existing lock doesn't match the requested one.  Return a lock mismatch error
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                FB.UpdateLockInfo(document, ex.Message);
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.ServerError, Message = ex.Message
                });
            }
        }