public MacVol(VolStruc vol, MyDSI3 comm, ConDyn cd, IDir parentDir) { this.vol = vol; this.comm = comm; this.cd = cd; this.parentDir = parentDir; }
public static string Getfp(String pwd, String unixPath, ConDyn cd) { if (unixPath == null) return pwd; if (unixPath.StartsWith("/")) { return Getfp("/", unixPath.Substring(1), cd); } int p = unixPath.IndexOf('/'); String s1 = (p < 0) ? unixPath : unixPath.Substring(0, p); String s2 = (p < 0) ? null : unixPath.Substring(1 + p); if (s1 == ".") { return Getfp(pwd, s2, cd); } if (s1 == "..") { return Getfp(GetParent(pwd), s2, cd); } return Getfp(pwd.TrimEnd('/') + "/" + s1, s2, cd); }
public MacRoot Login(MyDSI3 comm, ConDyn cd, String U, String P) { { TransmitRes res = comm.Transmit(new DSIOpenSession()); if (res.pack.IsResponse && res.pack.ErrorCode == 0) { } else { throw new ApplicationException("DSIOpenSessionに失敗"); } } { TransmitRes res = comm.Transmit(new DSICommand().WithRequestPayload(new FPLogin_Cleartext_Password() .WithUserName(U) .WithPasswd(P) .WithAFPVersion("AFP2.2")) ); if (res.pack.IsResponse && res.pack.ErrorCode == 0) { } else { throw new ApplicationException("FPLoginに失敗"); } } { TransmitRes res1 = comm.Transmit(new DSICommand().WithRequestPayload(new FPGetSrvrParms())); if (res1.pack.IsResponse && res1.pack.ErrorCode == 0) { } else { throw new ApplicationException("FPGetSrvrParmsに失敗"); } GetSrvrParmsPack pack = new GetSrvrParmsPack(res1.br); return new MacRoot(pack, comm, cd); } }
public static Stream Createf(IDir self, String unixPath, ConDyn cd) { if (unixPath == null) throw new StorException("unixPath is null"); if (unixPath.StartsWith("/")) { return Createf(GetRoot(self), unixPath.Substring(1), cd); } int p = unixPath.IndexOf('/'); String s1 = (p < 0) ? unixPath : unixPath.Substring(0, p); String s2 = (p < 0) ? null : unixPath.Substring(1 + p); if (s1 == ".") { return Createf(self, s2, cd); } if (s1 == "..") { return Createf(self.ParentDir, s2, cd); } if (s2 == null) { MacfNam m2 = cd.ParseName(s1); try { self.CreatefHere(m2.Name); } catch (DSIException err) { if (err.ErrorCode == (int)AFPt2.DSIException.ResultCode.kFPObjectExists) { } else throw new StorException("Failed", err); } IEnt o2 = self.FindReal(m2.Name); if (false) { } else if (m2.Ty == Forkty.Data && o2 is ICanUP) return ((ICanUP)o2).OpenWrite(false); else if (m2.Ty == Forkty.Res && o2 is ICanUP) return ((ICanUP)o2).OpenWrite(true); else if (m2.Ty == Forkty.Finder && o2 is ICanUPFi) return ((ICanUPFi)o2).OpenWriteFinder(); else throw new StorException("We can't write to \"" + o2.Name + "\"."); } IEnt o = self.FindReal(s1); if (o is IDir) { return Createf((IDir)o, s2, cd); } else if (o != null) { throw new StorException("We knew \"" + o.Name + "\" is a file."); } throw new StorException("We can't be here for \"" + o.Name + "\"."); }
public static Object Dele(IDir self, String unixPath, ConDyn cd) { if (unixPath == null) throw new DeleException("unixPath is null"); if (unixPath.StartsWith("/")) { return Dele(GetRoot(self), unixPath.Substring(1), cd); } int p = unixPath.IndexOf('/'); String s1 = (p < 0) ? unixPath : unixPath.Substring(0, p); String s2 = (p < 0) ? null : unixPath.Substring(1 + p); if (s1 == ".") { return Dele(self, s2, cd); } if (s1 == "..") { return Dele(self.ParentDir, s2, cd); } if (s2 == null) { MacfNam m2 = cd.ParseName(s1); IEnt o2 = self.FindReal(m2.Name); if (false) { } else if (m2.Ty == Forkty.Data && o2 is ICanDele) ((ICanDele)o2).DeletefMe(false); else if (m2.Ty == Forkty.Res && o2 is ICanDele) ((ICanDele)o2).DeletefMe(true); else if (m2.Ty == Forkty.Finder && o2 is ICanDeleFi) ((ICanDeleFi)o2).DeletefMeFinder(); else throw new DeleException("We can't delete \"" + o2.Name + "\"."); return null; } IEnt o = self.FindReal(s1); if (o is IDir) { return Dele((IDir)o, s2, cd); } else if (o != null) { throw new DeleException("We knew \"" + o.Name + "\" is a file."); } throw new DeleException("We can't be here for \"" + s1 + "\"."); }
public MacRoot(GetSrvrParmsPack pack, MyDSI3 comm, ConDyn cd) { this.pack = pack; this.comm = comm; this.cd = cd; }
// https://developer.apple.com/library/mac/documentation/networking/Reference/AFP_Reference/Reference/reference.html#//apple_ref/c/func/FPOpenDir void T2(object state) { Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; Encoding enc = Encoding.GetEncoding(932); ManualResetEvent evExit = new ManualResetEvent(false); try { using (TcpClient tcp = (TcpClient)state) { NetworkStream st = tcp.GetStream(); StreamWriter wr = new StreamWriter(st, Encoding.UTF8); StreamReader rr = new StreamReader(st, Encoding.UTF8, false); ConDyn cd = new ConDyn(cc); String syst = ""; using (MyDSI3 comm = new MyDSI3(afp)) { TransmitRes res = comm.Transmit(new DSIGetStatus()); if (res.pack.IsResponse && res.pack.ErrorCode == 0) { GetSrvrInfoPack pack = new GetSrvrInfoPack(res.br); if (pack.AFPVersionsList.Contains("AFP2.2")) { } if (pack.AFPVersionsList.Contains("AFPX03")) { cd.AFP30 = true; } if (pack.AFPVersionsList.Contains("AFP3.1")) { cd.AFP31 = true; } syst += " Server: " + pack.ServerName + "\n"; syst += " AFPVer:"; foreach (String ver in pack.AFPVersionsList) syst += " <" + ver + ">"; syst += "\n"; syst += " UAM:"; foreach (String ver in pack.UAMsList) syst += " <" + ver + ">"; } else { Ut.WriteRes(wr, 500, "AFP server failed: " + new DSIException(res.pack.ErrorCode, res.pack)); return; } } String U = String.Empty; String P = String.Empty; IDir root = new DisconnetedRoot(); IDir pwd = root; DataConn dc = new DataConn(); Int64 ftpRest = 0; IEnt rnfr = null; using (MyDSI3 comm = new MyDSI3(afp)) { Ticker ti = new Ticker(comm, evExit); Ut.WriteRes(wr, 220, "FTP4AFP in UTF-8"); while (true) { try { String row = rr.ReadLine(); if (row == null) break; Match M; M = Regex.Match(row, "^QUIT", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { Ut.WriteRes(wr, 221, "Goodbye!"); break; } M = Regex.Match(row, "^USER\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { U = M.Groups["a"].Value; Ut.WriteRes(wr, 331, "Proceed to password."); continue; } M = Regex.Match(row, "^PASS\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { P = M.Groups["a"].Value; Uta a = new Uta(); root = pwd = a.Login(comm, cd, U, P); Ut.WriteRes(wr, 230, "User logged in, proceed."); continue; } M = Regex.Match(row, "^SYST", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { Ut.WriteRes(wr, 215, typeof(AFPServ).AssemblyQualifiedName + "\n" + Environment.OSVersion + "\n" + "\n" + syst); continue; } M = Regex.Match(row, "^(XPWD|PWD)", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { MLoc m = MLoc.Ut.Get(pwd); Ut.WriteRes(wr, 257, "\"" + m.UnixPath + "\" is current directory."); continue; } M = Regex.Match(row, "^TYPE\\s+(?<a>A|I)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String mode = M.Groups["a"].Value.ToUpperInvariant(); if (mode == "I") dc.TypeI(); if (mode == "A") dc.TypeA(); Ut.WriteRes(wr, 200, "Ok."); continue; } M = Regex.Match(row, "^PASV", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { dc.Pasv(tcp.Client.LocalEndPoint); Ut.WriteRes(wr, 227, "Entering Passive Mode (" + dc.GetPasv() + ")"); continue; } M = Regex.Match(row, "^PORT\\s+(?<a>\\d+,\\d+,\\d+,\\d+,\\d+,\\d+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { dc.Port(M.Groups["a"].Value); Ut.WriteRes(wr, 200, "PORT command successful."); continue; } M = Regex.Match(row, "^LIST(\\s+(?<a>.+))?\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { IDir newwd = (cwd.Length == 0) ? pwd : TravUt.Cwd(pwd, cwd); StringWriter ww = new StringWriter(); foreach (IEnt o in newwd.GetEnts()) { bool isDir = o is IDir; ww.WriteLine("{0}rw-r--r-- 1 0 0 {1,10} {2,-12} {3}" , isDir ? "d" : "-" , isDir ? "0" : o.Size.ToString() , DUt.Format(o.Mt) , o.Name ); } // http://blog.livedoor.jp/kumagai_nori/archives/51660940.html // http://ash.jp/net/ftp_command.htm // http://www.atmarkit.co.jp/ait/articles/0307/11/news001.html // http://www.atmarkit.co.jp/fnetwork/rensai/netpro10/ftp-responsecode.html // http://maruo.dyndns.org:81/hidesoft/hidesoft_2/x17565.html // http://www.nsftools.com/tips/MSFTP.htm#dir Ut.WriteRes(wr, 150, "Opening " + dc.Mode + " mode data connection for LIST"); dc.SendData(wr.Encoding.GetBytes(ww.ToString())); Ut.WriteRes(wr, 226, "Transfer complete"); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 501, err.Message); continue; } } M = Regex.Match(row, "^MLSD(\\s+(?<a>.+))?\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { IDir newwd = (cwd.Length == 0) ? pwd : TravUt.Cwd(pwd, cwd); StringWriter ww = new StringWriter(); foreach (IEnt o in newwd.GetEnts()) { bool isDir = o is IDir; ww.WriteLine("modify={0};perm={1};size={2};type={3}; {4}" , o.Mt.HasValue ? String.Format("{0:yyyy}{0:MM}{0:dd}{0:HH}{0:mm}{0:ss}", o.Mt.Value) : "" , isDir ? "cdelmp" : "dlrw" , Math.Max(o.Size, 0) , isDir ? "dir" : "file" , o.Name ); } Ut.WriteRes(wr, 150, "Opening " + dc.Mode + " mode data connection for MLSD"); dc.SendData(wr.Encoding.GetBytes(ww.ToString())); Ut.WriteRes(wr, 226, "Transfer complete"); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 501, err.Message); continue; } } M = Regex.Match(row, "^CWD\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { IDir newwd = TravUt.Cwd(pwd, cwd); pwd = newwd; Ut.WriteRes(wr, 250, "Directory successfully changed."); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, err.Message); continue; } } M = Regex.Match(row, "^CDUP", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { IDir newwd = pwd.ParentDir; if (newwd == null) { Ut.WriteRes(wr, 250, "We are already at root directory."); continue; } else { pwd = newwd; Ut.WriteRes(wr, 250, "Directory successfully changed."); continue; } } M = Regex.Match(row, "^OPTS\\s+UTF8\\s+ON\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { Ut.WriteRes(wr, 200, "It is in UTF8 mode."); wr = new StreamWriter(st, Encoding.UTF8); rr = new StreamReader(st, Encoding.UTF8, false); continue; } M = Regex.Match(row, "^OPTS\\s+UTF8\\s+OFF\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { Ut.WriteRes(wr, 200, "It is in " + enc.BodyName + " mode."); wr = new StreamWriter(st, enc); rr = new StreamReader(st, enc, false); continue; } M = Regex.Match(row, "^OPTS\\s+FORKMODE\\s+(?<a>\\d+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { int i = int.Parse(M.Groups["a"].Value); cd.ForkMode = i; Ut.WriteRes(wr, 200, "It is in fork mode " + i + "."); continue; } M = Regex.Match(row, "^FEAT", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { Ut.WriteRes(wr, 211, "Features:| UTF8| MLST modify*;perm*;size*;type*;| FORKMODE| END".Replace("|", "\n")); continue; } M = Regex.Match(row, "^RETR\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { IEnt source = TravUt.Find(pwd, cwd, false); if (source is ICanDL) { using (Stream si = ((ICanDL)source).OpenRead()) { Ut.WriteRes(wr, 150, "Opening " + dc.Mode + " mode data connection for " + cwd); si.Position = ftpRest; dc.SendSt(si); } } else { Ut.WriteRes(wr, 550, "We can't get \"" + cwd + "\"."); continue; } ftpRest = 0; Ut.WriteRes(wr, 226, "Transfer complete"); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, err.Message); continue; } } M = Regex.Match(row, "^STOR\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { using (Stream os = TravUt.Createf(pwd, cwd, cd)) { Ut.WriteRes(wr, 150, "Opening " + dc.Mode + " mode data connection for " + cwd); os.SetLength(ftpRest); os.Position = ftpRest; dc.RecvSt(os); } ftpRest = 0; Ut.WriteRes(wr, 226, "Transfer complete"); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, err.Message); continue; } } M = Regex.Match(row, "^APPE\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { using (Stream os = TravUt.Createf(pwd, cwd, cd)) { Ut.WriteRes(wr, 150, "Opening " + dc.Mode + " mode data connection for " + cwd); os.Seek(0, SeekOrigin.End); dc.RecvSt(os); } Ut.WriteRes(wr, 226, "Transfer complete"); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, err.Message); continue; } } M = Regex.Match(row, "^MKD\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { TravUt.CreateDir(pwd, cwd); Ut.WriteRes(wr, 250, "\"" + cwd + "\" created successfully."); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, "\"" + cwd + "\": Unable to create directory. \n" + err.Message); continue; } } M = Regex.Match(row, "^RMD\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { TravUt.RMDir(pwd, cwd); Ut.WriteRes(wr, 250, "\"" + cwd + "\" removed successfully."); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, "\"" + cwd + "\": Unable to remove directory. \n" + err.Message); continue; } } M = Regex.Match(row, "^DELE\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { TravUt.Dele(pwd, cwd, cd); Ut.WriteRes(wr, 250, "\"" + cwd + "\" removed successfully."); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, "\"" + cwd + "\": Unable to remove directory. \n" + err.Message); continue; } } M = Regex.Match(row, "^REST\\s+(?<a>\\d+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { ftpRest = Int64.Parse(M.Groups["a"].Value); Ut.WriteRes(wr, 200, "Ok."); continue; } M = Regex.Match(row, "^RNFR\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { rnfr = TravUt.Find(pwd, cwd, false); Ut.WriteRes(wr, 350, "The file exists, continue with RNTO."); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, err.Message); continue; } } M = Regex.Match(row, "^RNTO\\s+(?<a>.+)\\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (M.Success) { String cwd = M.Groups["a"].Value; try { MLoc mfrm = MLoc.Ut.Get(rnfr); String fpfrm = mfrm.UnixPath; MLoc m = MLoc.Ut.Get(pwd); String fp2 = UtPLoc.Getfp(m.UnixPath, cwd, cd); PLoc p1 = new PLoc(fpfrm); PLoc p2 = new PLoc(fp2); if (!p1.volume.Equals(p2.volume)) throw new ApplicationException("We have different volumes."); if (!p1.dir.Equals(p2.dir)) { MLoc m2 = new MLoc(); m2.VolID = mfrm.VolID; m2.DirID = mfrm.DirID; m2.MacVol = mfrm.MacVol; m2.MacPath = p2.dir.Replace("/", "\0"); Utcmd.Move(comm, mfrm, m2, p2.fname); } else { Utcmd.Rename(comm, mfrm, p2.fname); } Ut.WriteRes(wr, 200, "Ok."); continue; } catch (EntNotFoundException err) { Ut.WriteRes(wr, 550, err.Message); continue; } } Ut.WriteRes(wr, 500, "NotImpl Error."); } catch (Exception err) { if (tcp.Connected) { try { Ut.WriteRes(wr, 500, err.ToString()); } catch (IOException) { } } else break; } } } tcp.Close(); } } finally { evExit.Set(); } }
public MacDir(FileParameters parm, MyDSI3 comm, ConDyn cd, IDir parentDir) { this.parm = parm; this.comm = comm; this.cd = cd; this.parentDir = parentDir; }
public static IEnt FindReal(string name, MyDSI3 comm, ConDyn cd, IDir self) { MLoc m = MLoc.Ut.Get(self); TransmitRes res = comm.Transmit(new DSICommand().WithRequestPayload(new FPGetFileDirParms() .WithVolumeID(m.VolID) .WithDirectoryID(m.DirID) .WithFileBitmap(AfpFileBitmap.LongName | AfpFileBitmap.NodeID | (cd.ExtRW ? (AfpFileBitmap.ExtDataForkLength | AfpFileBitmap.ExtResourceForkLength) : AfpFileBitmap.DataForkLength | AfpFileBitmap.ResourceForkLength)) .WithDirectoryBitmap(AfpDirectoryBitmap.NodeID | AfpDirectoryBitmap.LongName) .WithPath(PUt.CombineRaw(m.RawPath, name)) )); if (res.pack.IsResponse && res.pack.ErrorCode == 0) { } else if (res.pack.ErrorCode == (int)AFPt2.DSIException.ResultCode.kFPObjectNotFound) { return null; } else throw new DSIException(res.pack.ErrorCode, res.pack); GetFileDirParmsPack pack = new GetFileDirParmsPack(res.br); FileParameters ent = pack.Parms; if (ent.IsDirectory) { return new MacDir(ent, comm, cd, self); } else { return new MacEnt(ent, Forkty.Data, comm, cd, self); } }
public static IEnumerable<IEnt> GetEnts310(MLoc m, MyDSI3 comm, ConDyn cd, IDir self) { for (uint x = 0; ; ) { TransmitRes res1 = comm.Transmit(new DSICommand().WithRequestPayload(new FPEnumerateExt2() .WithPath(m.RawPath) .WithStartIndex(Convert.ToUInt32(1U + x)) .WithVolumeID(m.VolID) .WithDirectoryID(m.DirID) .WithFileBitmap(AfpFileBitmap.ExtDataForkLength | AfpFileBitmap.ExtResourceForkLength | AfpFileBitmap.LongName | AfpFileBitmap.NodeID | AfpFileBitmap.ModificationDate) .WithDirectoryBitmap(AfpDirectoryBitmap.NodeID | AfpDirectoryBitmap.LongName | AfpDirectoryBitmap.ModificationDate) )); if (res1.pack.ErrorCode == -5018) break; if (res1.pack.IsResponse && res1.pack.ErrorCode == 0) { } else { throw new DSIException(res1.pack.ErrorCode, res1.pack); } EnumerateExtPack pack = new EnumerateExtPack(res1.br); foreach (FileParameters ent in pack.Ents) { if (ent.IsDirectory) { yield return new MacDir(ent, comm, cd, self); } else { yield return new MacEnt(ent, Forkty.Data, comm, cd, self); if (cd.EnumRes && ((Utfs.ResFork(ent) > 0) || !cd.IfAvail)) yield return new MacEnt(ent, Forkty.Res, comm, cd, self); if (cd.EnumFi) yield return new MacEnt(ent, Forkty.Finder, comm, cd, self); } } if (pack.ActualCount == 0) break; x += pack.ActualCount; } }
public static IEnumerable<IEnt> GetEnts(MLoc m, MyDSI3 comm, ConDyn cd, IDir self) { if (cd.AFP31) return GetEnts310(m, comm, cd, self); if (cd.AFP30) return GetEnts300(m, comm, cd, self); return GetEnts220(m, comm, cd, self); }
public MacEnt(FileParameters parm, Forkty ty, MyDSI3 comm, ConDyn cd, IDir parentDir) { this.parm = parm; this.ty = ty; this.comm = comm; this.cd = cd; this.parentDir = parentDir; }