mirror of https://gitee.com/apiumc/Gateway.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
679 lines
32 KiB
C#
679 lines
32 KiB
C#
using System.Collections.Generic;
|
|
using System.IO.Compression;
|
|
// using System.Net;
|
|
using System;
|
|
using System.Linq;
|
|
using UMC.SshNet;
|
|
using UMC.Web;
|
|
using UMC.Web.UI;
|
|
using UMC.Net;
|
|
|
|
namespace UMC.ITME.Activities;
|
|
|
|
|
|
[Apiumc("Proxy", "SSH", Auth = WebAuthType.User)]
|
|
class SiteSSHActivities : Web.WebActivity
|
|
{
|
|
|
|
public static void SSHLog(Entities.Device device, string username, params string[] logs)
|
|
{
|
|
var file = UMC.Data.Reflection.ConfigPath($"Static\\log\\WebSSH\\{device.Ip}\\{username}.log");
|
|
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(file)))
|
|
{
|
|
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(file));
|
|
}
|
|
|
|
System.IO.File.AppendAllLines(file, logs);
|
|
}
|
|
public override void ProcessActivity(WebRequest request, WebResponse response)
|
|
{
|
|
var Key = this.AsyncDialog("Key", g =>
|
|
{
|
|
var form = request.SendValues ?? new WebMeta();
|
|
var limit = form["limit"] ?? "none";
|
|
|
|
var keys = new List<String>();
|
|
var user = this.Context.Token.Identity();
|
|
var searcher = UMC.Data.HotCache.Search<Entities.Device>();
|
|
|
|
var Keyword = form["Keyword"];
|
|
|
|
if (String.IsNullOrEmpty(Keyword) == false)
|
|
{
|
|
searcher.Or().Like(new Entities.Device { Caption = Keyword, Ip = Keyword, Username = Keyword, Desc = Keyword });
|
|
}
|
|
switch (limit)
|
|
{
|
|
case "PC":
|
|
{
|
|
var sts = new System.Data.DataTable();
|
|
sts.Columns.Add("id");
|
|
sts.Columns.Add("ip");
|
|
sts.Columns.Add("caption");
|
|
sts.Columns.Add("user");
|
|
sts.Columns.Add("port");
|
|
sts.Columns.Add("type");
|
|
|
|
var ds = searcher.Query(new Entities.Device(), false, 0, 500, out var index);
|
|
Utility.Each(ds, r => keys.Add($"WebSSH/{r.Id}"));
|
|
|
|
var auths = UMC.Security.AuthManager.Authorization(user, 0, keys.ToArray());
|
|
var count = 0; int i = 0;
|
|
foreach (var d in ds)
|
|
{
|
|
if (auths[i].Item1 > 0)
|
|
{
|
|
count++;
|
|
sts.Rows.Add(d.Id, d.Ip, d.Caption, d.Username, d.Port, d.Type);
|
|
}
|
|
i++;
|
|
}
|
|
var rdata = new WebMeta().Put("data", sts);
|
|
|
|
if (count == 0)
|
|
{
|
|
if (String.IsNullOrEmpty(Keyword))
|
|
{
|
|
rdata.Put("msg", "未有可访问的设备");
|
|
}
|
|
else
|
|
{
|
|
rdata.Put("msg", $"未搜索到“{Keyword}”相关可访问的设备");
|
|
}
|
|
|
|
}
|
|
var lic = UMC.Data.License.GetLicense("WebSSH", 5);
|
|
|
|
Data.Caches.ICacheSet cacheSet = UMC.Data.HotCache.Cache<Entities.Device>();
|
|
if ((cacheSet.Count > lic.Quantity && lic.Quantity > 0) || (lic.ExpireTime > 0 && lic.ExpireTime < Utility.TimeSpan()))
|
|
{
|
|
|
|
response.Redirect("System", "License", new Web.UIConfirmDialog("设备数量超限,请保持合规.")
|
|
{
|
|
Title = "版权授权",
|
|
DefaultValue = "WebSSH"
|
|
}, false);
|
|
}
|
|
|
|
this.Context.Send("WebSSH", request.IsMaster ? rdata.Put("IsMaster", true) : rdata, true);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
var title = UITitle.Create();
|
|
|
|
title.Title = "我的设备";
|
|
|
|
var ds = searcher.Query(new Entities.Device(), false, 0, 500, out var index);
|
|
Utility.Each(ds, r => keys.Add($"WebSSH/{r.Id}"));
|
|
var auths = UMC.Security.AuthManager.Authorization(user, 0, keys.ToArray());
|
|
if (request.IsMaster)
|
|
title.Right(new UIEventText().Icon('\ue907').Click(new UIClick(request, g, "Create")));
|
|
var ui = UISection.Create(title);
|
|
var webr = UMC.Data.WebResource.Instance();
|
|
var count = 0;
|
|
int i = 0;
|
|
foreach (var d in ds)
|
|
{
|
|
if (auths[i].Item1 > 0)
|
|
{
|
|
var item = new UIIconNameDesc.Item('\uf17c', d.Caption, $"{d.Username}@{d.Ip}");
|
|
count++;
|
|
UIIconNameDesc uIIcon = new UIIconNameDesc(item);
|
|
item.Color(0x111);
|
|
item.Click(new UIClick(request, g, d.Id.ToString()));
|
|
if (request.IsMaster)
|
|
{
|
|
ui.Delete(uIIcon, new UIEventText("删除").Click(new UIClick(request, g, d.Id.ToString(), "Model", "Remove")));
|
|
}
|
|
else
|
|
{
|
|
ui.Add(uIIcon);
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
if (count == 0)
|
|
{
|
|
if (String.IsNullOrEmpty(Keyword))
|
|
{
|
|
var desc = new UIDesc("未有可访问的设备");
|
|
desc.Put("icon", "\uf016").Format("desc", "{icon}\n{desc}");
|
|
desc.Style.Align(1).Color(0xaaa).Padding(20, 20).BgColor(0xfff).Size(12).Name("icon", new UIStyle().Font("wdk").Size(60));
|
|
ui.Add(desc);
|
|
}
|
|
else
|
|
{
|
|
var desc = new UIDesc($"未搜索到“{Keyword}”相关可访问的设备");
|
|
desc.Put("icon", "\uf016").Format("desc", "{icon}\n{desc}");
|
|
desc.Style.Align(1).Color(0xaaa).Padding(20, 20).BgColor(0xfff).Size(12).Name("icon", new UIStyle().Font("wdk").Size(60));
|
|
ui.Add(desc);
|
|
}
|
|
}
|
|
ui.SendTo(this.Context, true, $"{request.Model}.{request.Command}");
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
return this.DialogValue("none");
|
|
});
|
|
switch (Key)
|
|
{
|
|
case "Create":
|
|
Create();
|
|
break;
|
|
}
|
|
var device = UMC.Data.HotCache.Get(new Entities.Device { Id = Utility.IntParse(Key, 0) });
|
|
var model = this.AsyncDialog("Model", g =>
|
|
{
|
|
int start = UMC.Data.Utility.IntParse(request.SendValues?["start"] as string, 0);
|
|
var nextKey = request.SendValues?["NextKey"] ?? "Header";
|
|
|
|
UISection ui = null;
|
|
UISection pathUI = null;
|
|
if (start == 0 && String.Equals(nextKey, "Header"))
|
|
{
|
|
ui = UISection.Create(new UITitle("设备信息"));
|
|
ui.AddCell("设备名称", device.Caption, new UIClick(request, g, "Editer"));
|
|
|
|
var cell = UI.UI("登录地址", $"{device.Ip}:{device.Port}");
|
|
|
|
if (request.IsMaster && request.IsApp == false)
|
|
{
|
|
ui.Delete(cell, new UIEventText("删除").Click(new UIClick(request, g, "Remove")));
|
|
}
|
|
else
|
|
{
|
|
ui.Add(cell);
|
|
}
|
|
ui.AddCell("用户名", device.Username);
|
|
if (request.IsMaster)
|
|
{
|
|
if (String.IsNullOrEmpty(device.Desc) == false)
|
|
{
|
|
ui.AddCell("描述", device.Desc);
|
|
}
|
|
ui.AddCell("设置权限", new UIClick("Settings", "AuthKey", new WebMeta().Put("Key", $"WebSSH/{device.Id}")));
|
|
}
|
|
pathUI = ui.NewSection();
|
|
|
|
}
|
|
else
|
|
{
|
|
ui = pathUI = UISection.Create();
|
|
}
|
|
pathUI.Key = "Path";
|
|
var path = this.AsyncDialog("Path", "/");
|
|
var password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(device.Ip, device.Username));
|
|
try
|
|
{
|
|
using (var sftp = new SftpClient(new PasswordConnectionInfo(device.Ip, device.Port ?? 22, device.Username, password)))
|
|
{
|
|
sftp.Connect();
|
|
var sftpFiles = sftp.ListDirectory(path).OrderByDescending(r => r.IsDirectory).Where(f => f.Name != "." && f.Name != "..");
|
|
if (String.Equals(path, "/"))
|
|
{
|
|
pathUI.AddCell('\uf0e8', "根目录", "/");
|
|
}
|
|
else
|
|
{
|
|
var name = path.LastIndexOf('/', path.Length - 1);
|
|
var parentPath = path.Substring(0, name);
|
|
var click = request.IsApp ? UIClick.Query("Path", new WebMeta("Path", String.IsNullOrEmpty(parentPath) ? "/" : parentPath)) : UIClick.UIEvent("Search", new WebMeta("key", "Path").Put("search", new WebMeta("Path", path.Substring(0, name))));// UIClick.Click(new UIClick(request, "Path", path.Substring(0, name), "Model", "Next"));
|
|
if (sftpFiles.Count() == 0)
|
|
{
|
|
var cell = UICell.Create("UI", new WebMeta("value", path.Substring(name + 1)).Put("text", "当前目录").Put("Icon", '\uf0e8').Put("click", click));
|
|
pathUI.Delete(cell, new UIEventText("删除").Click(UIClick.Click(new UIClick(request, g, "Del", "Path", path + "/"))));
|
|
|
|
var desc = new UIDesc($"当前目录没有文件或子目录");
|
|
desc.Put("icon", "\uf016").Format("desc", "{icon}\n{desc}");
|
|
desc.Style.Align(1).Color(0xaaa).Padding(20, 20).BgColor(0xfff).Size(12).Name("icon", new UIStyle().Font("wdk").Size(60));
|
|
pathUI.Add(desc);
|
|
}
|
|
else
|
|
{
|
|
pathUI.AddCell('\uf0e8', "当前目录", path.Substring(name + 1), click);
|
|
}
|
|
}
|
|
foreach (var file in sftpFiles)
|
|
{
|
|
if (file.IsDirectory)
|
|
{
|
|
pathUI.AddCell('\uf114', file.Name, "", request.IsApp ? UIClick.Query("Path", new WebMeta("Path", file.FullName)) : UIClick.UIEvent("Search", new WebMeta("key", "Path").Put("search", new WebMeta("Path", file.FullName))));// ("Path", file.FullName)));
|
|
}
|
|
else
|
|
{
|
|
var cell = UICell.Create("UI", new WebMeta("value", Utility.GetBitSize(file.Length)).Put("text", file.Name).Put("Icon", '\uf0f6').Put("click", new UIClick(request, g, file.Length > 1000000 ? "Down" : "View", "Path", file.FullName)));
|
|
pathUI.Delete(cell, new UIEventText("删除").Click(new UIClick(request, g, "Del", "Path", file.FullName)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var desc = new UIDesc(ex.Message);
|
|
pathUI.Add(desc);
|
|
}
|
|
ui.UIFootBar = new UIFootBar() { IsFixed = true };
|
|
ui.UIFootBar.AddIcon(new UIEventText('\uf0ee', "上传").Click(new UIClick(request, g, "UploadFile")));
|
|
ui.UIFootBar.AddText(new UIEventText("新建目录").Click(new UIClick(request, g, "New")),
|
|
new UIEventText("终端打开").Click(new UIClick(request, g, "Open")).Style(new UIStyle().BgColor()));
|
|
|
|
ui.SendTo($"OpenPath,UploadFile,{request.Model}.{request.Command}.Remove", this.Context, true, $"{request.Model}.{request.Command}");
|
|
|
|
});
|
|
var Path = this.AsyncDialog("Path", "/");
|
|
var password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(device.Ip, device.Username));
|
|
//
|
|
switch (model)
|
|
{
|
|
case "Next":
|
|
{
|
|
var webMeta = new WebMeta(request.Arguments);
|
|
|
|
webMeta.Remove("Model");
|
|
this.Context.Send("ViewPath", new WebMeta().Put("Path", Path), false);
|
|
this.Context.Send(new WebMeta().UIEvent("Search", this.AsyncDialog("UI", "none"), new WebMeta("key", "Path").Put("send", webMeta)), true);
|
|
|
|
}
|
|
break;
|
|
case "Editer":
|
|
{
|
|
var config = this.AsyncDialog("Settings", g =>
|
|
{
|
|
var from = new Web.UIFormDialog() { Title = "设备" };
|
|
from.AddTextValue().Put("登录地址", $"{device.Ip}:{device.Port}").Put("用户名", device.Username);
|
|
|
|
from.AddText("名称", "Caption", device.Caption);
|
|
|
|
from.AddText("描述", "Desc", device.Desc).NotRequired();//.Put("tip", String.Empty);
|
|
from.Submit("确认修改", $"{this.Context.Request.Model}.{this.Context.Request.Command}");
|
|
return from;
|
|
});
|
|
Data.HotCache.Put(new Entities.Device
|
|
{
|
|
Id = device.Id,
|
|
Desc = config["Desc"],
|
|
Caption = config["Caption"]
|
|
});
|
|
this.Context.Send($"{this.Context.Request.Model}.{this.Context.Request.Command}", true);
|
|
|
|
}
|
|
break;
|
|
case "UploadFile":
|
|
if (request.IsApp)
|
|
{
|
|
request.Arguments["Model"] = "File";
|
|
goto case "Dir";
|
|
}
|
|
else
|
|
{
|
|
this.Context.Send("UploadFile", new WebMeta().Put("Path", Path), true);
|
|
}
|
|
break;
|
|
case "Dir":
|
|
case "File":
|
|
{
|
|
var media_id = this.AsyncDialog("media_id", g =>
|
|
{
|
|
if (request.IsApp)
|
|
{
|
|
return Web.UIDialog.Create("File");
|
|
}
|
|
else
|
|
{
|
|
var from = new Web.UIFormDialog() { Title = "上传文件" };
|
|
var conf = from.AddFile("选择资源", "media_id", String.Empty).Put("Accept", "*/*").Put("Multiple", true);
|
|
|
|
switch (model)
|
|
{
|
|
case "Dir":
|
|
from.Title = "上传文件夹";
|
|
conf.Put("Dir", true);
|
|
break;
|
|
}
|
|
from.Submit("确认上传");
|
|
return from;
|
|
}
|
|
});
|
|
var deviceKey = Utility.Guid(this.AsyncDialog("Device", "none"));
|
|
var filePath = String.Format("{0}{1}", Path, Path.EndsWith('/') ? "" : "/");
|
|
if (media_id.StartsWith("http://") || media_id.StartsWith("https://"))
|
|
{
|
|
var url = new Uri(media_id);
|
|
var name = Uri.UnescapeDataString(url.AbsolutePath.Substring(url.AbsolutePath.LastIndexOf('/') + 1));
|
|
|
|
url.WebRequest().Get(r =>
|
|
{
|
|
if (r.StatusCode == System.Net.HttpStatusCode.OK)
|
|
{
|
|
var tempFile = System.IO.Path.GetTempFileName();
|
|
var stream = System.IO.File.Open(tempFile, System.IO.FileMode.Create);
|
|
|
|
r.ReadAsData((b, i, c) =>
|
|
{
|
|
if (c == 0 && b.Length == 0)
|
|
{
|
|
if (i == -1)
|
|
{
|
|
this.Prompt("Web SSH", "上传失败", false);
|
|
stream.Close();
|
|
System.IO.File.Delete(tempFile);
|
|
}
|
|
else
|
|
{
|
|
stream.Flush();
|
|
stream.Close();
|
|
try
|
|
{
|
|
Upload(name, filePath, tempFile, device, password, deviceKey);
|
|
this.Prompt("上传成功", false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.Prompt("上传错误", ex.Message, false);
|
|
}
|
|
}
|
|
this.Context.Send(false);
|
|
this.Context.OutputFinish();
|
|
}
|
|
else
|
|
{
|
|
stream.Write(b, i, c);
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
|
|
this.Prompt("Web SSH", "上传失败", false);
|
|
this.Context.OutputFinish();
|
|
}
|
|
});
|
|
response.Redirect(Empty);
|
|
}
|
|
else
|
|
{
|
|
media_id = Uri.UnescapeDataString(media_id);
|
|
var filename = UMC.Data.Reflection.ConfigPath(String.Format("Static\\TEMP\\{0}", media_id.Substring(media_id.IndexOf('/', 2) + 1)));
|
|
|
|
var name = media_id.Substring(media_id.LastIndexOf('/') + 1);
|
|
try
|
|
{
|
|
Upload(name, filePath, filename, device, password, deviceKey);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.Prompt("上传错误", ex.Message);
|
|
}
|
|
this.Context.Send(true);
|
|
}
|
|
|
|
}
|
|
break;
|
|
case "Open":
|
|
if (request.IsApp)
|
|
{
|
|
String url;
|
|
if (Path == "/")
|
|
{
|
|
|
|
url = new Uri(request.Url, $"/WebSSH/{device.Id}/").AbsoluteUri;
|
|
}
|
|
else
|
|
{
|
|
url = new Uri(request.Url, $"/WebSSH/{device.Id}{Path}/").AbsoluteUri;
|
|
|
|
}
|
|
var webMeta = new WebMeta();
|
|
webMeta.Put("value", url);
|
|
webMeta.Put("right", new UIEventText().Icon('\uf11c').Click(UIClick.Click(new UIClick(request, "Model", "Keyboard"))));
|
|
this.Context.Send("OpenUrl", webMeta, true);
|
|
}
|
|
else
|
|
{
|
|
this.Context.Send("OpenPath", new WebMeta().Put("Path", Path), true);
|
|
}
|
|
break;
|
|
case "Keyboard":
|
|
{
|
|
var ui = this.AsyncDialog("UI", "none");
|
|
var Paste = this.AsyncDialog("PasteText", r =>
|
|
{
|
|
var s = new UISheetDialog() { Title = "快捷键" };
|
|
|
|
s.CloseEvent = $"{request.Model}.{request.Command}";
|
|
s.Cells(3);
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b"))) { Text = "ESC" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b[A"))) { Text = "↑" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u0003"))) { Text = "Ctrl + C" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b[D"))) { Text = "←" });
|
|
s.Put(new UIClick("CaseCMS", new UIClick(request)) { Text = "粘贴" });
|
|
|
|
// s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Refresh", ui, new WebMeta().Put("type", "Keyboard", "value", "\t"))) { Text = "刷新" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b[C"))) { Text = "→" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b[H"))) { Text = "Home" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b[B"))) { Text = "↓" });
|
|
s.Put(new UIClick("Event", new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", "\u001b[F"))) { Text = "END" });
|
|
|
|
return s;
|
|
});
|
|
this.Context.Send(new WebMeta().UIEvent("UI.Callback", ui, new WebMeta().Put("type", "Keyboard", "value", Paste)), true);
|
|
}
|
|
break;
|
|
case "New":
|
|
{
|
|
var filePath = String.Format("{0}{1}", Path, Path.EndsWith('/') ? "" : "/");
|
|
var dir = this.AsyncDialog("DirName", r => new UITextDialog() { Title = "新建文件夹" });
|
|
using (var sftp = new SftpClient(new PasswordConnectionInfo(device.Ip, device.Port ?? 22, device.Username, password)))
|
|
{
|
|
sftp.Connect();
|
|
|
|
sftp.CreateDirectory(filePath + dir);
|
|
|
|
}
|
|
this.Context.Send(true);
|
|
}
|
|
break;
|
|
case "Download":
|
|
response.Redirect(new Uri(request.Url, $"/WebSSH/{device.Id}{Path}"));
|
|
break;
|
|
case "Edit":
|
|
this.Context.Send("Markdown", new WebMeta().Put("submit", new UIClick(request, "Model", "Content")), true);
|
|
break;
|
|
case "Down":
|
|
case "View":
|
|
this.AsyncDialog("View", r =>
|
|
{
|
|
var value = UIClick.Markdown(new UIClick(request, "Model", "Content")); value.Text = "编辑";
|
|
var s = new UISheetDialog() { Title = "文件选择" };
|
|
s.Put(new UIClick(new Uri(request.Url, $"/WebSSH/{device.Id}{Path}").AbsoluteUri) { Key = "Url", Text = "下载" });
|
|
if (model == "View")
|
|
s.Put(value);
|
|
return s;
|
|
});
|
|
break;
|
|
case "Content":
|
|
{
|
|
using (var sftp = new SftpClient(new PasswordConnectionInfo(device.Ip, device.Port ?? 22, device.Username, password)))
|
|
{
|
|
sftp.Connect();
|
|
var Content = this.AsyncDialog("Content", r =>
|
|
{
|
|
String s = String.Empty;
|
|
try
|
|
{
|
|
s = sftp.ReadAllText(Path);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.Prompt("打开失败", ex.Message);
|
|
}
|
|
|
|
response.Redirect(new WebMeta().Put("Content", s).Put("title", Path));
|
|
|
|
});
|
|
sftp.WriteAllText(Path, Content);
|
|
|
|
SSHLog(device, this.Context.Token.Username, $"upload {Path}");
|
|
}
|
|
}
|
|
break;
|
|
case "Remove":
|
|
{
|
|
UMC.Data.HotCache.Delete(new Entities.Device { Id = Utility.IntParse(Key, 0) });
|
|
|
|
this.Context.Send($"{request.Model}.{request.Command}.Remove", true);
|
|
}
|
|
break;
|
|
case "Del":
|
|
{
|
|
using (var sftp = new SftpClient(new PasswordConnectionInfo(device.Ip, device.Port ?? 22, device.Username, password)))
|
|
{
|
|
sftp.Connect();
|
|
if (Path.EndsWith('/'))
|
|
{
|
|
var delPath = Path.Substring(0, Path.Length - 1);
|
|
sftp.DeleteDirectory(delPath);
|
|
SSHLog(device, this.Context.Token.Username, $"rmdir {delPath}");
|
|
var webMeta = new WebMeta(request.Arguments);
|
|
|
|
webMeta.Remove("Model");
|
|
|
|
var nameIndex = delPath.LastIndexOf('/');
|
|
webMeta.Put("Path", nameIndex == 0 ? "/" : delPath.Substring(0, nameIndex));
|
|
this.Context.Send("ViewPath", new WebMeta().Put("Path", webMeta["Path"]), false);
|
|
this.Context.Send(new WebMeta().UIEvent("Search", this.AsyncDialog("UI", "none"), new WebMeta("key", "Path").Put("send", webMeta)), true);
|
|
}
|
|
else
|
|
{
|
|
sftp.Delete(Path);
|
|
SSHLog(device, this.Context.Token.Username, $"rm {Path}");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
void Upload(string name, string path, string filename, Entities.Device device, string password, Guid? deviceKey)
|
|
{
|
|
var filePath = String.Format("{0}{1}", path, path.EndsWith('/') ? "" : "/", name);
|
|
|
|
using (var sftp = new SftpClient(new PasswordConnectionInfo(device.Ip, device.Port ?? 22, device.Username, password)))
|
|
{
|
|
sftp.Connect();
|
|
if (name.EndsWith(".umczip"))
|
|
{
|
|
|
|
var fs = ZipFile.OpenRead(filename).Entries;
|
|
var fsCount = fs.Count;
|
|
int ucount = 0;
|
|
foreach (var f in fs)
|
|
{
|
|
ucount++;
|
|
if (f.Length > 0)
|
|
{
|
|
var fnames = new List<String>(f.FullName.Split('/'));
|
|
fnames.RemoveAt(fnames.Count - 1);
|
|
var sbf = new System.Text.StringBuilder();
|
|
sbf.Append(filePath);
|
|
for (var i = 0; i < fnames.Count; i++)
|
|
{
|
|
if (i > 0)
|
|
{
|
|
sbf.Append('/');
|
|
}
|
|
sbf.Append(fnames[i]);
|
|
if (sftp.Exists(sbf.ToString()) == false)
|
|
{
|
|
sftp.CreateDirectory(sbf.ToString());
|
|
}
|
|
}
|
|
|
|
using (var stm = f.Open())
|
|
{
|
|
var now = Utility.TimeSpan();
|
|
sftp.UploadFile(stm, filePath + f.FullName, true, (v) =>
|
|
{
|
|
if (deviceKey.HasValue)
|
|
{
|
|
var old = Utility.TimeSpan();
|
|
if (old - now > 0)
|
|
{
|
|
Host.HttpWebSocket.Send(deviceKey.Value, UMC.Data.JSON.Serialize(new WebMeta("type", "progress", "value", $"{f.Name}({ucount}/{fsCount}) {v * 100 / ((ulong)f.Length)}%")));
|
|
now = old;
|
|
}
|
|
}
|
|
});
|
|
SSHLog(device, this.Context.Token.Username, $"upload {filePath + f.FullName}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (var s = System.IO.File.OpenRead(filename))
|
|
{
|
|
var now = Utility.TimeSpan();
|
|
sftp.UploadFile(s, filePath + name, true, (v) =>
|
|
{
|
|
if (deviceKey.HasValue)
|
|
{
|
|
var old = Utility.TimeSpan();
|
|
if (old - now > 0)
|
|
{
|
|
Host.HttpWebSocket.Send(deviceKey.Value, UMC.Data.JSON.Serialize(new WebMeta("type", "progress", "value", $"{name} {v * 100 / ((ulong)s.Length)}%")));
|
|
now = old;
|
|
}
|
|
}
|
|
});
|
|
SSHLog(device, this.Context.Token.Username, $"upload {filePath + name}");
|
|
}
|
|
}
|
|
System.IO.File.Delete(filename);
|
|
|
|
}
|
|
}
|
|
|
|
void Create()
|
|
{
|
|
if (this.Context.Request.IsMaster == false)
|
|
{
|
|
this.Prompt("只有管理员才能新增设备");
|
|
}
|
|
|
|
var config = this.AsyncDialog("Settings", g =>
|
|
{
|
|
var from = new Web.UIFormDialog() { Title = "新增设备" };
|
|
|
|
from.AddText("名称", "Caption", String.Empty);
|
|
from.AddText("地址", "Ip", String.Empty).PlaceHolder("IP地址");
|
|
from.AddText("端口", "Port", "22");
|
|
from.AddText("用户名", "Username", String.Empty);
|
|
from.AddPassword("密码", "Password", String.Empty);
|
|
from.AddText("描述", "Desc", String.Empty).NotRequired().Put("tip", String.Empty);
|
|
from.Submit("确认新增", $"{this.Context.Request.Model}.{this.Context.Request.Command}");
|
|
return from;
|
|
});
|
|
|
|
var device = new Entities.Device { Id = Utility.TimeSpan(), Ip = config["Ip"], Port = Utility.IntParse(config["Port"], 22), Username = config["Username"], Desc = config["Desc"], Caption = config["Caption"], Type = Entities.DeviceType.Linux };
|
|
|
|
var ssh = new SshClient(device.Ip, device.Port.Value, device.Username, config["Password"]);
|
|
try
|
|
{
|
|
ssh.Connect();
|
|
ssh.Disconnect();
|
|
UMC.Data.HotCache.Put(device);
|
|
UMC.Data.DataFactory.Instance().Password(new Guid(Utility.MD5(device.Ip, device.Username)), config["Password"]);
|
|
this.Prompt("新增成功", false);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.Prompt("异常", ex.Message);
|
|
}
|
|
this.Context.Send($"{this.Context.Request.Model}.{this.Context.Request.Command}", true);
|
|
}
|
|
}
|