public static string GetShortestAbsolutePath(string strPath) { if (strPath == null) { throw new ArgumentNullException("strPath"); } if (strPath.Length == 0) { return(string.Empty); } // Path.GetFullPath is incompatible with UNC paths traversing over // different server shares (which are created by PathRelativePathTo); // we need to build the absolute path on our own... if (IsUncPath(strPath)) { char chSep = strPath[0]; char[] vSep = ((chSep == '/') ? (new char[] { '/' }) : (new char[] { '\\', '/' })); List <string> l = new List <string>(); #if !KeePassLibSD string[] v = strPath.Split(vSep, StringSplitOptions.None); #else string[] v = strPath.Split(vSep); #endif Debug.Assert((v.Length >= 3) && (v[0].Length == 0) && (v[1].Length == 0)); foreach (string strPart in v) { if (strPart.Equals(".")) { continue; } else if (strPart.Equals("..")) { if (l.Count > 0) { l.RemoveAt(l.Count - 1); } else { Debug.Assert(false); } } else { l.Add(strPart); // Do not ignore zero length parts } } StringBuilder sb = new StringBuilder(); for (int i = 0; i < l.Count; ++i) { // Don't test length of sb, might be 0 due to initial UNC seps if (i > 0) { sb.Append(chSep); } sb.Append(l[i]); } return(sb.ToString()); } string str; try { str = Path.GetFullPath(strPath); } catch (Exception) { Debug.Assert(false); return(strPath); } Debug.Assert((str.IndexOf("\\..\\") < 0) || NativeLib.IsUnix()); foreach (char ch in UrlUtil.DirSepChars) { string strSep = new string(ch, 1); str = str.Replace(strSep + "." + strSep, strSep); } return(str); }
public static string MakeRelativePath(string strBaseFile, string strTargetFile) { if (strBaseFile == null) { throw new ArgumentNullException("strBasePath"); } if (strTargetFile == null) { throw new ArgumentNullException("strTargetPath"); } if (strBaseFile.Length == 0) { return(strTargetFile); } if (strTargetFile.Length == 0) { return(string.Empty); } // Test whether on different Windows drives if ((strBaseFile.Length >= 3) && (strTargetFile.Length >= 3)) { if ((strBaseFile[1] == ':') && (strTargetFile[1] == ':') && (strBaseFile[2] == '\\') && (strTargetFile[2] == '\\') && (strBaseFile[0] != strTargetFile[0])) { return(strTargetFile); } } #if (!KeePassLibSD && !KeePassUAP && !KPCLib) if (NativeLib.IsUnix()) { #endif bool bBaseUnc = IsUncPath(strBaseFile); bool bTargetUnc = IsUncPath(strTargetFile); if ((!bBaseUnc && bTargetUnc) || (bBaseUnc && !bTargetUnc)) { return(strTargetFile); } string strBase = GetShortestAbsolutePath(strBaseFile); string strTarget = GetShortestAbsolutePath(strTargetFile); string[] vBase = strBase.Split(UrlUtil.DirSepChars); string[] vTarget = strTarget.Split(UrlUtil.DirSepChars); int i = 0; while ((i < (vBase.Length - 1)) && (i < (vTarget.Length - 1)) && (vBase[i] == vTarget[i])) { ++i; } StringBuilder sbRel = new StringBuilder(); for (int j = i; j < (vBase.Length - 1); ++j) { if (sbRel.Length > 0) { sbRel.Append(UrlUtil.LocalDirSepChar); } sbRel.Append(".."); } for (int k = i; k < vTarget.Length; ++k) { if (sbRel.Length > 0) { sbRel.Append(UrlUtil.LocalDirSepChar); } sbRel.Append(vTarget[k]); } return(sbRel.ToString()); #if (!KeePassLibSD && !KeePassUAP && !KPCLib) } try // Windows { const int nMaxPath = NativeMethods.MAX_PATH * 2; StringBuilder sb = new StringBuilder(nMaxPath + 2); if (!NativeMethods.PathRelativePathTo(sb, strBaseFile, 0, strTargetFile, 0)) { return(strTargetFile); } string str = sb.ToString(); while (str.StartsWith(".\\")) { str = str.Substring(2, str.Length - 2); } return(str); } catch (Exception) { Debug.Assert(false); } return(strTargetFile); #endif }