// 删除文件或者目录 // parameters: // strCurrentDirectory 当前路径,注意这是物理路径 // return: // -1 出错 // 其他 实际删除的文件和目录个数 public static int DeleteFile( string strRootPath, string strCurrentDirectory, string strPattern, out string strError) { strError = ""; try { FileSystemLoader loader = new FileSystemLoader(strCurrentDirectory, strPattern); loader.ListStyle = ListStyle.None; int count = 0; foreach (FileSystemInfo si in loader) { // 检查文件或目录必须在根以下。防止漏洞 if (PathUtil.IsChildOrEqual(si.FullName, strRootPath) == false) continue; if (si is DirectoryInfo) { PathUtil.DeleteDirectory(si.FullName); } if (si is FileInfo) { File.Delete(si.FullName); } count++; } return count; } catch (DirectoryNotFoundException) { return 0; } catch (Exception ex) { strError = ex.Message; return -1; } }
// 进行文件或目录上载 // return: // -1 出错 // 0 正常 int DoUpload(string strSource, string strTargetParam, out string strError) { strError = ""; int nRet = 0; FileSystemLoader loader = new FileSystemLoader(this._currentLocalDir, strSource); loader.ListStyle = ListStyle.None; // 对单一无匹配模式的目录对象不展开其下级 foreach (FileSystemInfo si in loader) { // string strSourcePath = GetLocalFullDirectory(strSource); string strSourcePath = si.FullName; string strTarget = strTargetParam; if (string.IsNullOrEmpty(strTargetParam) == true) strTarget = si.Name; if (si is DirectoryInfo) { string strServerFilePath = "!upload/" + GetFullDirectory(strTarget) + "/~" + Guid.NewGuid().ToString(); string strZipFileName = Path.GetTempFileName(); // TODO: 建议在当前目录创建临时文件,便于观察是否有删除遗漏,和处理 try { // return: // -1 出错 // 0 没有发现需要上传的文件 // 1 成功压缩创建了 .zip 文件 nRet = CompressDirecotry( strSourcePath, strZipFileName, Encoding.UTF8, out strError); if (nRet == -1) goto ERROR1; // return: // -1 出错 // 0 上传文件成功 nRet = UploadFile( null, this.Channel, strZipFileName, strServerFilePath, "extractzip", null, true, out strError); if (nRet == -1) goto ERROR1; Console.WriteLine(); Console.WriteLine("本地目录 " + si.FullName + " 成功上传到远程 " + GetFullDirectory(strTarget)); continue; } finally { File.Delete(strZipFileName); } } else if (si is FileInfo) { string strServerFilePath = "!upload/" + GetFullDirectory(strTarget); // return: // -1 出错 // 0 上传文件成功 nRet = UploadFile( null, this.Channel, strSourcePath, strServerFilePath, "", null, true, out strError); if (nRet == -1) goto ERROR1; Console.WriteLine(); Console.WriteLine("本地文件 " + si.FullName + " 成功上传到远程 " + GetFullDirectory(strTarget)); continue; } } return 0; ERROR1: return -1; }
// 返回的 FileItemInfo.Name 中是逻辑全路径 // parameters: // strCurrentDirectory 当前路径。物理路径 // return: // -1 出错 // 其他 列出的事项总数。注意,不是 lLength 所指出的本次返回数 public static int ListFile( string strRootPath, string strCurrentDirectory, string strPattern, long lStart, long lLength, out List<FileItemInfo> infos, out string strError) { strError = ""; infos = new List<FileItemInfo>(); int MAX_ITEMS = 100; // 一次 API 最多返回的事项数量 try { FileSystemLoader loader = new FileSystemLoader(strCurrentDirectory, strPattern); int i = 0; int count = 0; foreach (FileSystemInfo si in loader) { // 检查文件或目录必须在根以下。防止漏洞 if (PathUtil.IsChildOrEqual(si.FullName, strRootPath) == false) continue; if (i < lStart) goto CONTINUE; if (lLength != -1 && count > lLength) goto CONTINUE; if (count >= MAX_ITEMS) goto CONTINUE; FileItemInfo info = new FileItemInfo(); infos.Add(info); info.Name = si.FullName.Substring(strRootPath.Length); info.CreateTime = si.CreationTime.ToString("u"); if (si is DirectoryInfo) { info.Size = -1; // 表示这是目录 } if (si is FileInfo) { FileInfo fi = si as FileInfo; info.Size = fi.Length; } count++; CONTINUE: i++; } return i; } catch (DirectoryNotFoundException) { return 0; } catch (Exception ex) { strError = ex.Message; return -1; } }
// return: // false 正常,继续 // true 退出命令 public bool ProcessCommand(string line) { if (line == "exit" || line == "quit") return true; string strError = ""; int nRet = 0; List<string> parameters = ParseParameters(line); if (parameters.Count == 0) return false; if (parameters[0] == "login") { string strHost = ""; string strUserName = ""; string strPassword = ""; if (parameters.Count > 1) strHost = parameters[1]; if (parameters.Count > 2) strUserName = parameters[2]; if (parameters.Count > 3) strPassword = parameters[3]; if (parameters.Count <= 3) { if (GetUserNamePassword(out strHost, out strUserName, out strPassword) == true) return true; } nRet = Login(strHost, strUserName, strPassword, out strError); if (nRet == -1) { Console.WriteLine("登录失败: " + strError); return false; } Console.WriteLine("登录成功"); return false; } if (parameters[0] == "dir") { // 测试 .. // *.* // ..\ // ..\*.* // \ // \*.* string strDir = ""; if (parameters.Count > 1) strDir = parameters[1]; FileSystemLoader loader = new FileSystemLoader(this._currentLocalDir, strDir); int file_count = 0; int dir_count = 0; foreach (FileSystemInfo si in loader) { // TODO: 是否先得到 FullName ,再根据起点目录截断显示后部 if (si is DirectoryInfo) { AlignWrite(si.LastWriteTime.ToString("u") + " <dir> "); Console.WriteLine(si.Name + "/"); dir_count++; } if (si is FileInfo) { FileInfo info = si as FileInfo; AlignWrite(info.LastWriteTime.ToString("u") + info.Length.ToString().PadLeft(10, ' ') + " "); Console.WriteLine(info.Name); file_count++; } } Console.WriteLine(); if (dir_count > 0) AlignWriteLine(dir_count.ToString() + " direcotries"); if (file_count > 0 || dir_count == 0) AlignWriteLine(file_count.ToString() + " files"); return false; } if (parameters[0] == "cd") { if (parameters.Count == 1) { Console.WriteLine(this._currentLocalDir); // 显示当前路径 return false; } if (parameters.Count > 1) { string strDir = ""; string strParam = GetCdParmeter(parameters); if (strParam == ".") { // 当前路径不变 return false; } else { #if NO strDir = Path.Combine(this._currentLocalDir, strParam); // 上一句执行完,有可能是这样 strDir = '\publish\dp2libraryxe',没有盘符 #endif FileSystemLoader.ChangeDirectory(this._currentLocalDir, strParam, out strDir); } // 要检验一下目录是否存在 if (Directory.Exists(strDir) == false) { Console.WriteLine("本地目录 '" + strDir + "' 不存在"); return false; } strDir = (new DirectoryInfo(strDir)).FullName; this._currentLocalDir = strDir; } return false; } if (parameters[0] == "rdir") { List<FileItemInfo> filenames = null; string strDir = ""; if (parameters.Count > 1) strDir = parameters[1]; nRet = RemoteList( GetRemoteCurrentDir(), // "!upload/" + this._currentDir, strDir, out filenames, out strError); if (nRet == -1) { Console.WriteLine("Dir error: " + strError); return false; } string strDisplayDirectory = ""; int file_count = 0; int dir_count = 0; foreach (FileItemInfo info in filenames) { #if NO string strName = ""; string strTime = ""; string strSize = ""; ParseFileName(filename, out strName, out strTime, out strSize); #endif string strCurrent = Path.GetDirectoryName(info.Name); if (strCurrent != strDisplayDirectory) { Console.WriteLine(); Console.WriteLine("远程 " + strCurrent + " 的目录:"); Console.WriteLine(); strDisplayDirectory = strCurrent; } string strName = ""; if (strDisplayDirectory != null) { strName = info.Name.Substring(strDisplayDirectory.Length); if (String.IsNullOrEmpty(strName) == false && strName[0] == '\\') strName = strName.Substring(1); } else strName = info.Name; // TODO: 如何显示文件名是个问题。建议,处在当前目录的,只显示纯文件名;越过当前目录的,显示全路径 // 也可以一段一段显示。某一段的事项都是处于同一目录,就在前导显示一句目录名,后面就显示纯文件名 // 两种风格都可以实现了看看 if (info.Size == -1) { dir_count++; AlignWrite(info.CreateTime + " <dir> "); Console.WriteLine(strName); } else { file_count++; AlignWrite(info.CreateTime + info.Size.ToString().PadLeft(10, ' ') + " "); Console.WriteLine(strName); } } Console.WriteLine(); if (dir_count > 0) AlignWriteLine(dir_count.ToString() + " direcotries"); if (file_count > 0 || dir_count == 0) AlignWriteLine(file_count.ToString() + " files"); return false; } if (parameters[0] == "rcd") { if (parameters.Count == 1) { Console.WriteLine(this._currentDir); // 显示当前路径 return false; } #if NO string strDir = ""; if (parameters.Count > 1) strDir = parameters[1]; #endif string strDir = GetCdParmeter(parameters); string strResultDirectory = ""; // 进行远程 CD 命令 // parameters: // strCurrentDirectory 当前路径 // strPath 试图转去的路径 // strResultDirectory 返回成功转过去的结果路径。需把这个路径设为最新的当前路径 nRet = RemoteChangeDir( GetRemoteCurrentDir(), // "!upload" + this._currentDir, strDir, out strResultDirectory, out strError); if (nRet == -1) goto ERROR1; // 检查这个远程目录是否存在 this._currentDir = strResultDirectory; Debug.Assert(string.IsNullOrEmpty(this._currentDir) == true || this._currentDir.IndexOf("\\") == -1, "this._currentDir 中不允许使用字符 '\\'"); #if DEBUG if (string.IsNullOrEmpty(this._currentDir) == false) { Debug.Assert(this._currentDir[0] == '\\' || this._currentDir[0] == '/', "远程逻辑路径如果为非空,则第一字符应该是斜杠。但现在是 '" + this._currentDir + "'"); } #endif #if NO if (parameters.Count > 1) { string strDir = ""; if (parameters[1] == "..") { if (string.IsNullOrEmpty(this._currentDir) == true) { Console.WriteLine("远程目录当前已经是根目录了"); return false; } strDir = Path.GetDirectoryName(this._currentDir); } else if (parameters[1] == ".") { // 当前路径不变 return false; } else { // strDir = Path.Combine(this._currentDir, parameters[1]); strDir = GetFullDirectory(parameters[1]); } // 要检验一下目录是否存在 nRet = RemoteDirExists(strDir); if (nRet == -1) return false; if (nRet == 0) { Console.WriteLine("远程目录 '" + strDir + "' 不存在"); return false; } this._currentDir = strDir; } #endif return false; } if (parameters[0] == "upload") { if (parameters.Count < 2) { Console.WriteLine("upload 命令用法: upload 源文件或目录 [目标文件或目录]"); // 如果目标目录省略,则表示和源目录同名 return false; } string strSource = parameters[1]; // strSource 可能为 "*.*" 这样的模式 string strTarget = ""; // strTarget 可能空缺 if (parameters.Count > 2) strTarget = parameters[2]; nRet = DoUpload(strSource, strTarget, out strError); if (nRet == -1) goto ERROR1; return false; } if (parameters[0] == "rdel" || parameters[0] == "rdelete") { if (parameters.Count != 2) { Console.WriteLine("rdel 命令用法: rdel 远程目录"); return false; } string strDir = ""; if (parameters.Count > 1) strDir = parameters[1]; // 删除一个远程文件或者目录 nRet = RemoteDelete( GetRemoteCurrentDir(), strDir, out strError); if (nRet == -1) goto ERROR1; Console.WriteLine("已删除远程文件 " + nRet.ToString() + " 个"); return false; } if (parameters[0] == "download") { if (parameters.Count < 2) { Console.WriteLine("download 命令用法: download 源文件或目录 [目标文件或目录]"); // 如果目标目录省略,则表示和源目录同名 return false; } string strSource = parameters[1]; // strSource 可能为 "*.*" 这样的模式 string strTarget = ""; // strTarget 可能空缺 if (parameters.Count > 2) strTarget = parameters[2]; nRet = DoDownload(strSource, strTarget, out strError); if (nRet == -1) goto ERROR1; return false; } Console.WriteLine("unknown command '" + line + "'"); return false; ERROR1: Console.WriteLine(strError); return false; }