Exemplo n.º 1
0
        public static Stream OpenWrite(IOConnectionInfo ioc)
        {
            if (ioc == null)
            {
                Debug.Assert(false); return(null);
            }

            RaiseIOAccessPreEvent(ioc, IOAccessType.Write);

            if (ioc.IsLocalFile())
            {
                return(OpenWriteLocal(ioc));
            }

            Uri    uri = new Uri(ioc.Path);
            Stream s;

            // Mono does not set HttpWebRequest.Method to POST for writes,
            // so one needs to set the method to PUT explicitly
            if (NativeLib.IsUnix() && IsHttpWebRequest(uri))
            {
                s = CreateWebClient(ioc).OpenWrite(uri, WebRequestMethods.Http.Put);
            }
            else
            {
                s = CreateWebClient(ioc).OpenWrite(uri);
            }

            return(IocStream.WrapIfRequired(s));
        }
Exemplo n.º 2
0
        public static bool FileExists(IOConnectionInfo ioc, bool bThrowErrors)
        {
            if (ioc == null)
            {
                Debug.Assert(false); return(false);
            }

            RaiseIOAccessPreEvent(ioc, IOAccessType.Exists);

#if ModernKeePassLib
            return(ioc.Bytes != null);
#else
            if (ioc.IsLocalFile())
            {
                return(File.Exists(ioc.Path));
            }

#if !KeePassLibSD
            if (ioc.Path.StartsWith("ftp://", StrUtil.CaseIgnoreCmp))
            {
                bool b = SendCommand(ioc, WebRequestMethods.Ftp.GetDateTimestamp);
                if (!b && bThrowErrors)
                {
                    throw new InvalidOperationException();
                }
                return(b);
            }
#endif

            try
            {
                Stream s = OpenRead(ioc);
                if (s == null)
                {
                    throw new FileNotFoundException();
                }

                try { s.ReadByte(); }
                catch (Exception) { }

                // We didn't download the file completely; close may throw
                // an exception -- that's okay
                try { s.Close(); }
                catch (Exception) { }
            }
            catch (Exception)
            {
                if (bThrowErrors)
                {
                    throw;
                }
                return(false);
            }

            return(true);
#endif
        }
Exemplo n.º 3
0
        public static void DeleteFile(IOConnectionInfo ioc)
        {
            RaiseIOAccessPreEvent(ioc, IOAccessType.Delete);

#if ModernKeePassLib
            if (!ioc.IsLocalFile())
            {
                return;
            }
            MemUtil.ZeroByteArray(ioc.Bytes);
#else
            if (ioc.IsLocalFile())
            {
                File.Delete(ioc.Path); return;
            }

#if !KeePassLibSD
            WebRequest req = CreateWebRequest(ioc);
            if (req != null)
            {
                if (IsHttpWebRequest(req))
                {
                    req.Method = "DELETE";
                }
                else if (IsFtpWebRequest(req))
                {
                    req.Method = WebRequestMethods.Ftp.DeleteFile;
                }
                else if (IsFileWebRequest(req))
                {
                    File.Delete(UrlUtil.FileUrlToPath(ioc.Path));
                    return;
                }
                else
                {
                    req.Method = WrmDeleteFile;
                }

                DisposeResponse(req.GetResponse(), true);
            }
#endif
#endif
        }
Exemplo n.º 4
0
        public static Stream OpenRead(IOConnectionInfo ioc)
        {
            RaiseIOAccessPreEvent(ioc, IOAccessType.Read);

            if (StrUtil.IsDataUri(ioc.Path))
            {
                byte[] pbData = StrUtil.DataUriToData(ioc.Path);
                if (pbData != null)
                {
                    return(new MemoryStream(pbData, false));
                }
            }

            if (ioc.IsLocalFile())
            {
                return(OpenReadLocal(ioc));
            }

            return(IocStream.WrapIfRequired(CreateWebClient(ioc).OpenRead(
                                                new Uri(ioc.Path))));
        }
Exemplo n.º 5
0
        public FileTransactionEx(IOConnectionInfo iocBaseFile, bool bTransacted)
        {
            if (iocBaseFile == null)
            {
                throw new ArgumentNullException("iocBaseFile");
            }

            m_bTransacted = bTransacted;

            m_iocBase = iocBaseFile.CloneDeep();
            if (m_iocBase.IsLocalFile())
            {
                m_iocBase.Path = UrlUtil.GetShortestAbsolutePath(m_iocBase.Path);
            }

            string strPath = m_iocBase.Path;

#if !ModernKeePassLib
            if (m_iocBase.IsLocalFile())
            {
                try
                {
                    if (File.Exists(strPath))
                    {
                        // Symbolic links are realized via reparse points;
                        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503.aspx
                        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680.aspx
                        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365006.aspx
                        // Performing a file transaction on a symbolic link
                        // would delete/replace the symbolic link instead of
                        // writing to its target
                        FileAttributes fa = File.GetAttributes(strPath);
                        if ((long)(fa & FileAttributes.ReparsePoint) != 0)
                        {
                            m_bTransacted = false;
                        }
                    }
                    else
                    {
                        // If the base and the temporary file are in different
                        // folders and the base file doesn't exist (i.e. we can't
                        // backup the ACL), a transaction would cause the new file
                        // to have the default ACL of the temporary folder instead
                        // of the one of the base folder; therefore, we don't use
                        // a transaction when the base file doesn't exist (this
                        // also results in other applications monitoring the folder
                        // to see one file creation only)
                        m_bTransacted = false;
                    }
                }
                catch (Exception) { Debug.Assert(false); }
            }
#endif

#if !ModernKeePassLib
            // Prevent transactions for FTP URLs under .NET 4.0 in order to
            // avoid/workaround .NET bug 621450:
            // https://connect.microsoft.com/VisualStudio/feedback/details/621450/problem-renaming-file-on-ftp-server-using-ftpwebrequest-in-net-framework-4-0-vs2010-only
            if (strPath.StartsWith("ftp:", StrUtil.CaseIgnoreCmp) &&
                (Environment.Version.Major >= 4) && !NativeLib.IsUnix())
            {
                m_bTransacted = false;
            }
#endif

            foreach (KeyValuePair <string, bool> kvp in g_dEnabled)
            {
                if (strPath.StartsWith(kvp.Key, StrUtil.CaseIgnoreCmp))
                {
                    m_bTransacted = kvp.Value;
                    break;
                }
            }

            if (m_bTransacted)
            {
                m_iocTemp       = m_iocBase.CloneDeep();
                m_iocTemp.Path += StrTempSuffix;

                TxfPrepare();                 // Adjusts m_iocTemp
            }
            else
            {
                m_iocTemp = m_iocBase;
            }
        }
Exemplo n.º 6
0
        private void CommitWriteTransaction()
        {
            if (g_bExtraSafe)
            {
                if (!IOConnection.FileExists(m_iocTemp))
                {
                    throw new FileNotFoundException(m_iocTemp.Path +
                                                    MessageService.NewLine + KLRes.FileSaveFailed);
                }
            }

            bool bMadeUnhidden = UrlUtil.UnhideFile(m_iocBase.Path);

#if !ModernKeePassLib
            // 'All' includes 'Audit' (SACL), which requires SeSecurityPrivilege,
            // which we usually don't have and therefore get an exception;
            // trying to set 'Owner' or 'Group' can result in an
            // UnauthorizedAccessException; thus we restore 'Access' (DACL) only
            const AccessControlSections acs = AccessControlSections.Access;
#endif
            bool     bEfsEncrypted = false;
            byte[]   pbSec         = null;
            DateTime?otCreation    = null;

            bool bBaseExists = IOConnection.FileExists(m_iocBase);
            if (bBaseExists && m_iocBase.IsLocalFile())
            {
                // FileAttributes faBase = FileAttributes.Normal;
                try
                {
#if !ModernKeePassLib
                    FileAttributes faBase = File.GetAttributes(m_iocBase.Path);
                    bEfsEncrypted = ((long)(faBase & FileAttributes.Encrypted) != 0);
                    try { if (bEfsEncrypted)
                          {
                              File.Decrypt(m_iocBase.Path);
                          }
                    }                                                                           // For TxF
                    catch (Exception) { Debug.Assert(false); }
#endif
#if ModernKeePassLib
                    otCreation = m_iocBase.StorageFile.DateCreated.UtcDateTime;
#else
                    otCreation = File.GetCreationTimeUtc(m_iocBase.Path);
#endif
#if !ModernKeePassLib
                    // May throw with Mono
                    FileSecurity sec = File.GetAccessControl(m_iocBase.Path, acs);
                    if (sec != null)
                    {
                        pbSec = sec.GetSecurityDescriptorBinaryForm();
                    }
#endif
                }
                catch (Exception) { Debug.Assert(NativeLib.IsUnix()); }

                // if((long)(faBase & FileAttributes.ReadOnly) != 0)
                //	throw new UnauthorizedAccessException();
            }

            if (!TxfMove())
            {
                if (bBaseExists)
                {
                    IOConnection.DeleteFile(m_iocBase);
                }
                IOConnection.RenameFile(m_iocTemp, m_iocBase);
            }
            else
            {
                Debug.Assert(pbSec != null);
            }                                                 // TxF success => NTFS => has ACL

            try
            {
                // If File.GetCreationTimeUtc fails, it may return a
                // date with year 1601, and Unix times start in 1970,
                // so testing for 1971 should ensure validity;
                // https://msdn.microsoft.com/en-us/library/system.io.file.getcreationtimeutc.aspx
#if !ModernKeePassLib
                if (otCreation.HasValue && (otCreation.Value.Year >= 1971))
                {
                    File.SetCreationTimeUtc(m_iocBase.Path, otCreation.Value);
                }
#endif

#if !ModernKeePassLib
                if (bEfsEncrypted)
                {
                    try { File.Encrypt(m_iocBase.Path); }
                    catch (Exception) { Debug.Assert(false); }
                }

                // File.SetAccessControl(m_iocBase.Path, secPrev);
                // Directly calling File.SetAccessControl with the previous
                // FileSecurity object does not work; the binary form
                // indirection is required;
                // https://sourceforge.net/p/keepass/bugs/1738/
                // https://msdn.microsoft.com/en-us/library/system.io.file.setaccesscontrol.aspx
                if ((pbSec != null) && (pbSec.Length != 0))
                {
                    FileSecurity sec = new FileSecurity();
                    sec.SetSecurityDescriptorBinaryForm(pbSec, acs);

                    File.SetAccessControl(m_iocBase.Path, sec);
                }
#endif
            }
            catch (Exception) { Debug.Assert(false); }

            if (bMadeUnhidden)
            {
                UrlUtil.HideFile(m_iocBase.Path, true);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Rename/move a file. For local file system and WebDAV, the
        /// specified file is moved, i.e. the file destination can be
        /// in a different directory/path. In contrast, for FTP the
        /// file is renamed, i.e. its destination must be in the same
        /// directory/path.
        /// </summary>
        /// <param name="iocFrom">Source file path.</param>
        /// <param name="iocTo">Target file path.</param>
        public static void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo)
        {
            RaiseIOAccessPreEvent(iocFrom, iocTo, IOAccessType.Move);

#if !ModernKeePassLib
            if (iocFrom.IsLocalFile())
            {
                File.Move(iocFrom.Path, iocTo.Path); return;
            }

#if !KeePassLibSD
            WebRequest req = CreateWebRequest(iocFrom);
            if (req != null)
            {
                string strToCnc = UrlUtil.GetCanonicalUri(iocTo.Path);

                if (IsHttpWebRequest(req))
                {
#if KeePassUAP
                    throw new NotSupportedException();
#else
                    req.Method = "MOVE";
                    req.Headers.Set("Destination", strToCnc);                     // Full URL supported
#endif
                }
                else if (IsFtpWebRequest(req))
                {
#if KeePassUAP
                    throw new NotSupportedException();
#else
                    req.Method = WebRequestMethods.Ftp.Rename;
                    string strToName = UrlUtil.GetFileName(strToCnc);

                    // We're affected by .NET bug 621450:
                    // https://connect.microsoft.com/VisualStudio/feedback/details/621450/problem-renaming-file-on-ftp-server-using-ftpwebrequest-in-net-framework-4-0-vs2010-only
                    // Prepending "./", "%2E/" or "Dummy/../" doesn't work.

                    ((FtpWebRequest)req).RenameTo = strToName;
#endif
                }
                else if (IsFileWebRequest(req))
                {
                    File.Move(UrlUtil.FileUrlToPath(iocFrom.Path),
                              UrlUtil.FileUrlToPath(iocTo.Path));
                    return;
                }
                else
                {
#if KeePassUAP
                    throw new NotSupportedException();
#else
                    req.Method = WrmMoveFile;
                    req.Headers.Set(WrhMoveFileTo, strToCnc);
#endif
                }

#if !KeePassUAP // Unreachable code
                DisposeResponse(req.GetResponse(), true);
#endif
            }
#endif

            // using(Stream sIn = IOConnection.OpenRead(iocFrom))
            // {
            //	using(Stream sOut = IOConnection.OpenWrite(iocTo))
            //	{
            //		MemUtil.CopyStream(sIn, sOut);
            //		sOut.Close();
            //	}
            //
            //	sIn.Close();
            // }
            // DeleteFile(iocFrom);
#endif
        }