예제 #1
0
        /// <summary>
        /// Creates or updates this item in the remote storage.
        /// </summary>
        /// <param name="remoteStorageUri">Uri of the file to be created or updated in the remote storage.</param>
        /// <param name="newInfo">New information about the file or folder, such as modification date, attributes, custom data, etc.</param>
        /// <param name="mode">Specifies if a new file should be created or existing file should be updated.</param>
        /// <param name="content">New file content or null if the file content is not modified.</param>
        /// <param name="eTagOld">The ETag to be sent to the remote storage as part of the update request to make sure the content is not overwritten.</param>
        /// <param name="lockInfo">Information about the lock. Caller passes null if the item is not locked.</param>
        /// <returns>The new ETag returned from the remote storage.</returns>
        protected static async Task <string> CreateOrUpdateFileAsync(
            Uri remoteStorageUri, IFileSystemItemMetadata newInfo, FileMode mode, Stream content = null, string eTagOld = null, ServerLockInfo lockInfo = null)
        {
            string eTagNew = null;

            if (content != null || mode == FileMode.CreateNew)
            {
                long contentLength = content != null ? content.Length : 0;

                IWebRequestAsync request = await Program.DavClient.GetFileWriteRequestAsync(
                    remoteStorageUri, null, contentLength, 0, -1, lockInfo?.LockToken, eTagOld);

                // Update remote storage file content.
                using (Stream davContentStream = await request.GetRequestStreamAsync())
                {
                    if (content != null)
                    {
                        await content.CopyToAsync(davContentStream);
                    }

                    // Get the new ETag returned by the server (if any).
                    // We return the new ETag to the Engine to be stored with the file unlil the next update.
                    IWebResponseAsync response = await request.GetResponseAsync();

                    eTagNew = response.Headers["ETag"];
                    response.Close();
                }
            }
            return(eTagNew);
        }
        /// <summary>
        /// Creates instance of this class.
        /// </summary>
        /// <param name="url">URL to navigate to. This URL must redirect to a log-in page.</param>
        public WebBrowserLogin(Uri url, IWebRequestAsync request, WebDavSessionAsync davClient, ILog log)
        {
            this.url       = url;
            this.request   = request;
            this.davClient = davClient;
            this.log       = log;
            InitializeComponent();

            this.webView = new Microsoft.Web.WebView2.Wpf.WebView2();
            this.Loaded += WebBrowserLogin_Load;
            this.panel.Children.Add(this.webView);
        }
예제 #3
0
        /// <inheritdoc/>
        public async Task WriteAsync(IFileMetadata fileMetadata, Stream content = null)
        {
            if (MsOfficeHelper.IsMsOfficeLocked(UserFileSystemPath)) // Required for PowerPoint. It does not block the for writing.
            {
                throw new ClientLockFailedException("The file is blocked for writing.");
            }

            Logger.LogMessage($"{nameof(IFile)}.{nameof(WriteAsync)}()", UserFileSystemPath);

            ExternalDataManager customDataManager = Engine.CustomDataManager(UserFileSystemPath);
            // Send the ETag to the server as part of the update to ensure the file in the remote storge is not modified since last read.
            string oldEtag = await customDataManager.ETagManager.GetETagAsync();

            // Send the lock-token to the server as part of the update.
            string lockToken = (await customDataManager.LockManager.GetLockInfoAsync())?.LockToken;


            if (content != null)
            {
                long contentLength = content != null ? content.Length : 0;

                IWebRequestAsync request = await Program.DavClient.GetFileWriteRequestAsync(
                    new Uri(RemoteStoragePath), null, contentLength, 0, -1, lockToken, oldEtag);

                // Update remote storage file content.
                using (Stream davContentStream = await request.GetRequestStreamAsync())
                {
                    if (content != null)
                    {
                        await content.CopyToAsync(davContentStream);
                    }

                    // Get the new ETag returned by the server (if any).
                    IWebResponseAsync response = await request.GetResponseAsync();

                    string eTagNew = response.Headers["ETag"];
                    response.Close();

                    // Store ETag unlil the next update.
                    // This will also mark the item as not new, which is required for correct MS Office saving opertions.
                    await customDataManager.ETagManager.SetETagAsync(eTagNew);

                    // Update ETag in custom column displayed in file manager.
                    await customDataManager.SetCustomColumnsAsync(new[] { new FileSystemItemPropertyData((int)CustomColumnIds.ETag, eTagNew) });
                }
            }
        }
예제 #4
0
        /// <inheritdoc/>
        public async Task <byte[]> CreateFileAsync(IFileMetadata fileMetadata, Stream content = null)
        {
            string userFileSystemNewItemPath = Path.Combine(UserFileSystemPath, fileMetadata.Name);

            Logger.LogMessage($"{nameof(IFolder)}.{nameof(CreateFileAsync)}()", userFileSystemNewItemPath);

            Uri newFileUri = new Uri(new Uri(RemoteStoragePath), fileMetadata.Name);

            long contentLength = content != null ? content.Length : 0;

            IWebRequestAsync request = await Program.DavClient.GetFileWriteRequestAsync(newFileUri, null, contentLength);

            // Update remote storage file content.
            using (Stream davContentStream = await request.GetRequestStreamAsync())
            {
                if (content != null)
                {
                    await content.CopyToAsync(davContentStream);
                }

                // Get the new ETag returned by the server (if any).
                IWebResponseAsync response = await request.GetResponseAsync();

                string eTagNew = response.Headers["ETag"];
                response.Close();

                ExternalDataManager customDataManager = Engine.CustomDataManager(userFileSystemNewItemPath);

                // Store ETag unlil the next update.
                // This will also mark the item as not new, which is required for correct MS Office saving opertions.
                await customDataManager.ETagManager.SetETagAsync(eTagNew);

                customDataManager.IsNew = false; // Mark file as not new just in case the server did not return the ETag.

                // Update ETag in custom column displayed in file manager.
                await customDataManager.SetCustomColumnsAsync(new[] { new FileSystemItemPropertyData((int)CustomColumnIds.ETag, eTagNew) });
            }

            return(null);
        }
예제 #5
0
        /// <summary>
        /// Creates or updates file in the remote storage.
        /// </summary>
        /// <param name="remoteStorageUri">Uri of the file to be created or updated in the remote storage.</param>
        /// <param name="newInfo">New information about the file, such as modification date, attributes, custom data, etc.</param>
        /// <param name="mode">Specifies if a new file should be created or existing file should be updated.</param>
        /// <param name="content">New file content or null if the file content is not modified.</param>
        /// <param name="lockInfo">Information about the lock. Caller passes null if the item is not locked.</param>
        /// <returns>New ETag returned from the remote storage.</returns>
        protected async Task <string> CreateOrUpdateFileAsync(Uri remoteStorageUri, IFileBasicInfo newInfo, FileMode mode, Stream content = null, ServerLockInfo lockInfo = null)
        {
            string eTag      = null;
            string lockToken = null;

            // Get ETag and lock-token here and send it to the remote storage with the new item content/info.
            if (mode == FileMode.Open)
            {
                // Get ETag.
                eTag = await ETag.GetETagAsync(UserFileSystemPath);

                // Get lock-token.
                lockToken = lockInfo?.LockToken;
            }

            if (content != null || mode == FileMode.CreateNew)
            {
                long contentLength = content != null ? content.Length : 0;

                IWebRequestAsync request = await Program.DavClient.GetFileWriteRequestAsync(remoteStorageUri, null, contentLength, 0, -1, lockToken, eTag);

                // Update remote storage file content.
                using (Stream davContentStream = await request.GetRequestStreamAsync())
                {
                    if (content != null)
                    {
                        await content.CopyToAsync(davContentStream);
                    }

                    // Get ETag returned by the server, if any.
                    IWebResponseAsync response = await request.GetResponseAsync();

                    eTag = response.Headers["ETag"];
                    response.Close();
                }
            }
            return(eTag);
        }
예제 #6
0
        /// <summary>
        /// Event handler to process WebDAV errors.
        /// If server returns 401 or 302 response here we show the login dialog.
        /// </summary>
        /// <param name="sender">Request to the WebDAV server.</param>
        /// <param name="e">WebDAV error details.</param>
        private static void DavClient_WebDavError(IWebRequestAsync sender, WebDavErrorEventArgs e)
        {
            WebDavHttpException httpException = e.Exception as WebDavHttpException;

            log.Info($"\n{httpException?.Status.Code} {httpException?.Status.Description} {e.Exception.Message} ");
            if (httpException != null)
            {
                switch (httpException.Status.Code)
                {
                // 302 redirect to login page.
                case 302:
                    if (loginRetriesCurrent < loginRetriesMax)
                    {
                        loginRetriesCurrent++;

                        // Show login dialog.

                        // Azure AD can not navigate directly to login page - failed corelation.
                        //string loginUrl = ((Redirect302Exception)e.Exception).Location;
                        //Uri url = new System.Uri(loginUrl, System.UriKind.Absolute);

                        Uri failedUri = (e.Exception as WebDavHttpException).Uri;

                        WebDAVDrive.UI.WebBrowserLogin webBrowserLogin = null;
                        Thread thread = new Thread(() => {
                            webBrowserLogin       = new WebDAVDrive.UI.WebBrowserLogin(failedUri, e.Request, DavClient, log);
                            webBrowserLogin.Title = Settings.ProductName;
                            webBrowserLogin.ShowDialog();
                        });
                        thread.SetApartmentState(ApartmentState.STA);
                        thread.Start();
                        thread.Join();

                        /*
                         * if (loginForm.Cookies != null)
                         * {
                         *  // Attach cookies to all future requests.
                         *  DavClient.CookieContainer.Add(loginForm.Cookies);
                         *  e.Result = WebDavErrorEventResult.Fail;
                         *
                         *  // Set successful response and continue processing.
                         *  e.Response = loginForm.Response;
                         *  e.Result = WebDavErrorEventResult.ContinueProcessing;
                         *
                         *  // Alternatively you can modify this request, attaching cookies or headers, and replay it.
                         *  //e.Request.CookieContainer.Add(loginForm.Cookies);
                         *  //e.Result = WebDavErrorEventResult.Repeat;
                         * }
                         */
                    }
                    break;

                // Challenge-responce auth: Basic, Digest, NTLM or Kerberos
                case 401:
                    if (loginRetriesCurrent < loginRetriesMax)
                    {
                        Uri failedUri = (e.Exception as WebDavHttpException).Uri;
                        Windows.Security.Credentials.PasswordCredential passwordCredential = CredentialManager.GetCredentials(Settings.ProductName, log);
                        if (passwordCredential != null)
                        {
                            passwordCredential.RetrievePassword();
                            DavClient.Credentials = new NetworkCredential(passwordCredential.UserName, passwordCredential.Password);
                        }
                        else
                        {
                            string       login        = null;
                            SecureString password     = null;
                            bool         dialogResult = false;
                            bool         keepLogedin  = false;

                            // Show login dialog
                            WebDAVDrive.UI.ChallengeLogin loginForm = null;
                            Thread thread = new Thread(() =>
                            {
                                loginForm = new WebDAVDrive.UI.ChallengeLogin();
                                ((ChallengeLoginViewModel)loginForm.DataContext).Url         = failedUri.OriginalString;
                                ((ChallengeLoginViewModel)loginForm.DataContext).WindowTitle = Settings.ProductName;
                                loginForm.ShowDialog();

                                login        = ((ChallengeLoginViewModel)loginForm.DataContext).Login;
                                password     = ((ChallengeLoginViewModel)loginForm.DataContext).Password;
                                keepLogedin  = ((ChallengeLoginViewModel)loginForm.DataContext).KeepLogedIn;
                                dialogResult = (bool)loginForm.DialogResult;
                            });
                            thread.SetApartmentState(ApartmentState.STA);
                            thread.Start();
                            thread.Join();

                            loginRetriesCurrent++;
                            if (dialogResult)
                            {
                                if (keepLogedin)
                                {
                                    CredentialManager.SaveCredentials(Settings.ProductName, login, password);
                                }
                                DavClient.Credentials = new NetworkCredential(login, password);
                            }
                        }
                    }
                    break;
                }
            }
        }