diff --git a/Plugins/Wox.Plugin.Fanyi/HttpRequest.cs b/Plugins/Wox.Plugin.Fanyi/HttpRequest.cs
index 8d0939e1ed..dd9b2fdc90 100644
--- a/Plugins/Wox.Plugin.Fanyi/HttpRequest.cs
+++ b/Plugins/Wox.Plugin.Fanyi/HttpRequest.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
@@ -10,20 +9,10 @@ using System.Text;
//From:http://blog.csdn.net/zhoufoxcn/article/details/6404236
namespace Wox.Plugin.Fanyi
{
- ///
- /// 有关HTTP请求的辅助类
- ///
public class HttpRequest
{
private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
- ///
- /// 创建GET方式的HTTP请求
- ///
- /// 请求的URL
- /// 请求的超时时间
- /// 请求的客户端浏览器信息,可以为空
- /// 随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空
- ///
+
public static HttpWebResponse CreateGetHttpResponse(string url, int? timeout, string userAgent, CookieCollection cookies)
{
if (string.IsNullOrEmpty(url))
@@ -48,16 +37,7 @@ namespace Wox.Plugin.Fanyi
}
return request.GetResponse() as HttpWebResponse;
}
- ///
- /// 创建POST方式的HTTP请求
- ///
- /// 请求的URL
- /// 随同请求POST的参数名称及参数值字典
- /// 请求的超时时间
- /// 请求的客户端浏览器信息,可以为空
- /// 发送HTTP请求时所用的编码
- /// 随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空
- ///
+
public static HttpWebResponse CreatePostHttpResponse(string url, IDictionary parameters, int? timeout, string userAgent, Encoding requestEncoding, CookieCollection cookies)
{
if (string.IsNullOrEmpty(url))
@@ -69,7 +49,6 @@ namespace Wox.Plugin.Fanyi
throw new ArgumentNullException("requestEncoding");
}
HttpWebRequest request = null;
- //如果是发送HTTPS请求
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
@@ -101,7 +80,6 @@ namespace Wox.Plugin.Fanyi
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(cookies);
}
- //如果需要POST数据
if (!(parameters == null || parameters.Count == 0))
{
StringBuilder buffer = new StringBuilder();
@@ -129,7 +107,7 @@ namespace Wox.Plugin.Fanyi
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
- return true; //总是接受
+ return true;
}
}
}
diff --git a/Plugins/Wox.Plugin.PluginManagement/HttpRequest.cs b/Plugins/Wox.Plugin.PluginManagement/HttpRequest.cs
new file mode 100644
index 0000000000..9596edeb71
--- /dev/null
+++ b/Plugins/Wox.Plugin.PluginManagement/HttpRequest.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+
+//From:http://blog.csdn.net/zhoufoxcn/article/details/6404236
+namespace Wox.Plugin.PluginManagement
+{
+ public class HttpRequest
+ {
+ private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
+
+ public static HttpWebResponse CreateGetHttpResponse(string url, int? timeout, string userAgent, CookieCollection cookies)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException("url");
+ }
+ HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
+ request.Method = "GET";
+ request.UserAgent = DefaultUserAgent;
+ if (!string.IsNullOrEmpty(userAgent))
+ {
+ request.UserAgent = userAgent;
+ }
+ if (timeout.HasValue)
+ {
+ request.Timeout = timeout.Value;
+ }
+ if (cookies != null)
+ {
+ request.CookieContainer = new CookieContainer();
+ request.CookieContainer.Add(cookies);
+ }
+ return request.GetResponse() as HttpWebResponse;
+ }
+
+ public static HttpWebResponse CreatePostHttpResponse(string url, IDictionary parameters, int? timeout, string userAgent, Encoding requestEncoding, CookieCollection cookies)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException("url");
+ }
+ if (requestEncoding == null)
+ {
+ throw new ArgumentNullException("requestEncoding");
+ }
+ HttpWebRequest request = null;
+ if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
+ {
+ ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
+ request = WebRequest.Create(url) as HttpWebRequest;
+ request.ProtocolVersion = HttpVersion.Version10;
+ }
+ else
+ {
+ request = WebRequest.Create(url) as HttpWebRequest;
+ }
+ request.Method = "POST";
+ request.ContentType = "application/x-www-form-urlencoded";
+
+ if (!string.IsNullOrEmpty(userAgent))
+ {
+ request.UserAgent = userAgent;
+ }
+ else
+ {
+ request.UserAgent = DefaultUserAgent;
+ }
+
+ if (timeout.HasValue)
+ {
+ request.Timeout = timeout.Value;
+ }
+ if (cookies != null)
+ {
+ request.CookieContainer = new CookieContainer();
+ request.CookieContainer.Add(cookies);
+ }
+ if (!(parameters == null || parameters.Count == 0))
+ {
+ StringBuilder buffer = new StringBuilder();
+ int i = 0;
+ foreach (string key in parameters.Keys)
+ {
+ if (i > 0)
+ {
+ buffer.AppendFormat("&{0}={1}", key, parameters[key]);
+ }
+ else
+ {
+ buffer.AppendFormat("{0}={1}", key, parameters[key]);
+ }
+ i++;
+ }
+ byte[] data = requestEncoding.GetBytes(buffer.ToString());
+ using (Stream stream = request.GetRequestStream())
+ {
+ stream.Write(data, 0, data.Length);
+ }
+ }
+ return request.GetResponse() as HttpWebResponse;
+ }
+
+ private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
+ {
+ return true;
+ }
+ }
+}
diff --git a/Plugins/Wox.Plugin.PluginManagement/Main.cs b/Plugins/Wox.Plugin.PluginManagement/Main.cs
index 43179414d2..fd49442c71 100644
--- a/Plugins/Wox.Plugin.PluginManagement/Main.cs
+++ b/Plugins/Wox.Plugin.PluginManagement/Main.cs
@@ -2,15 +2,37 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace Wox.Plugin.PluginManagement
{
+ public class WoxPlugin
+ {
+ public int apiVersion { get; set; }
+ public List result { get; set; }
+ }
+
+ public class WoxPluginResult
+ {
+ public string downloadUrl;
+ public string author;
+ public string description;
+ public string id;
+ public string language;
+ public int like;
+ public string name;
+ }
+
+
public class Main : IPlugin
{
private static string PluginPath = AppDomain.CurrentDomain.BaseDirectory + "Plugins";
private static string PluginConfigName = "plugin.json";
+ private static string pluginSearchUrl = "http://www.getwox.com/api/plugin/search/";
private PluginInitContext context;
public List Query(Query query)
@@ -20,12 +42,12 @@ namespace Wox.Plugin.PluginManagement
{
results.Add(new Result()
{
- Title = "wpm list",
- SubTitle = "list plugins installed",
+ Title = "wpm install ",
+ SubTitle = "search and install wox plugins",
IcoPath = "Images\\plugin.png",
Action = e =>
{
- context.ChangeQuery("wpm list");
+ context.ChangeQuery("wpm install ");
return false;
}
});
@@ -40,26 +62,147 @@ namespace Wox.Plugin.PluginManagement
return false;
}
});
+ results.Add(new Result()
+ {
+ Title = "wpm list",
+ SubTitle = "list plugins installed",
+ IcoPath = "Images\\plugin.png",
+ Action = e =>
+ {
+ context.ChangeQuery("wpm list");
+ return false;
+ }
+ });
return results;
}
if (query.ActionParameters.Count > 0)
{
+ bool hit = false;
switch (query.ActionParameters[0].ToLower())
{
case "list":
+ hit = true;
results = ListInstalledPlugins();
break;
case "uninstall":
+ hit = true;
results = ListUnInstalledPlugins(query);
break;
+
+ case "install":
+ hit = true;
+ if (query.ActionParameters.Count > 1)
+ {
+ results = InstallPlugin(query);
+ }
+ break;
+ }
+
+ if (!hit)
+ {
+ if ("install".Contains(query.ActionParameters[0].ToLower()))
+ {
+ results.Add(new Result()
+ {
+ Title = "wpm install ",
+ SubTitle = "search and install wox plugins",
+ IcoPath = "Images\\plugin.png",
+ Action = e =>
+ {
+ context.ChangeQuery("wpm install ");
+ return false;
+ }
+ });
+ }
+ if ("uninstall".Contains(query.ActionParameters[0].ToLower()))
+ {
+ results.Add(new Result()
+ {
+ Title = "wpm uninstall ",
+ SubTitle = "uninstall plugin",
+ IcoPath = "Images\\plugin.png",
+ Action = e =>
+ {
+ context.ChangeQuery("wpm uninstall ");
+ return false;
+ }
+ });
+ }
+ if ("list".Contains(query.ActionParameters[0].ToLower()))
+ {
+ results.Add(new Result()
+ {
+ Title = "wpm list",
+ SubTitle = "list plugins installed",
+ IcoPath = "Images\\plugin.png",
+ Action = e =>
+ {
+ context.ChangeQuery("wpm list");
+ return false;
+ }
+ });
+ }
}
}
return results;
}
+ private List InstallPlugin(Query query)
+ {
+ List results = new List();
+ HttpWebResponse response = HttpRequest.CreateGetHttpResponse(pluginSearchUrl + query.ActionParameters[1], null, null, null);
+ Stream s = response.GetResponseStream();
+ if (s != null)
+ {
+ StreamReader reader = new StreamReader(s, Encoding.UTF8);
+ string json = reader.ReadToEnd();
+ WoxPlugin o = JsonConvert.DeserializeObject(json);
+ foreach (WoxPluginResult r in o.result)
+ {
+ WoxPluginResult r1 = r;
+ results.Add(new Result()
+ {
+ Title = r.name,
+ SubTitle = r.description,
+ IcoPath = "Images\\plugin.png",
+ Action = e =>
+ {
+ string folder = Path.Combine(Path.GetTempPath(), "WoxPluginDownload");
+ if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
+ string filePath = Path.Combine(folder, Guid.NewGuid().ToString() + ".wox");
+
+ context.StartLoadingBar();
+ ThreadPool.QueueUserWorkItem(delegate
+ {
+ using (WebClient Client = new WebClient())
+ {
+ try
+ {
+ Client.DownloadFile(r1.downloadUrl, filePath);
+ context.InstallPlugin(filePath);
+ context.ReloadPlugins();
+ }
+ catch (Exception exception)
+ {
+ MessageBox.Show("download plugin " + r.name + "failed. " + exception.Message);
+ }
+ finally
+ {
+ context.StopLoadingBar();
+ }
+ }
+ });
+ return false;
+ }
+ });
+ }
+ }
+ return results;
+ }
+
private List ListUnInstalledPlugins(Query query)
{
List results = new List();
@@ -90,10 +233,10 @@ namespace Wox.Plugin.PluginManagement
private void UnInstalledPlugins(PluginMetadata plugin)
{
- string content = string.Format("Do you want to uninstall following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}",plugin.Name, plugin.Version, plugin.Author);
+ string content = string.Format("Do you want to uninstall following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}", plugin.Name, plugin.Version, plugin.Author);
if (MessageBox.Show(content, "Wox", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
- File.Create(Path.Combine(plugin.PluginDirecotry, "NeedDelete.txt"));
+ File.Create(Path.Combine(plugin.PluginDirecotry, "NeedDelete.txt")).Close();
MessageBox.Show("This plugin has been removed, restart Wox to take effect");
}
}
diff --git a/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj b/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj
index e8c7d2ff46..4ce95001e1 100644
--- a/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj
+++ b/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj
@@ -44,6 +44,7 @@
+
diff --git a/Wox.Plugin/PluginInitContext.cs b/Wox.Plugin/PluginInitContext.cs
index 38013797e9..fae6d758d9 100644
--- a/Wox.Plugin/PluginInitContext.cs
+++ b/Wox.Plugin/PluginInitContext.cs
@@ -25,5 +25,9 @@ namespace Wox.Plugin
///
public Action ReloadPlugins { get; set; }
+ public Action InstallPlugin { get; set; }
+
+ public Action StartLoadingBar { get; set; }
+ public Action StopLoadingBar { get; set; }
}
}
diff --git a/Wox/Helper/PluginInstaller.cs b/Wox/Helper/PluginInstaller.cs
index 1780609713..7288080417 100644
--- a/Wox/Helper/PluginInstaller.cs
+++ b/Wox/Helper/PluginInstaller.cs
@@ -1,9 +1,7 @@
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Text;
using System.Windows;
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
@@ -14,7 +12,6 @@ namespace Wox.Helper
{
public class PluginInstaller
{
-
public static void Install(string path)
{
if (File.Exists(path))
@@ -46,43 +43,51 @@ namespace Wox.Helper
Directory.CreateDirectory(pluginFolerPath);
}
- string newPluginPath = Path.Combine(pluginFolerPath, plugin.Name);
+ string newPluginPath = Path.Combine(pluginFolerPath, Guid.NewGuid().ToString());
string content = string.Format(
"Do you want to install following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}",
plugin.Name, plugin.Version, plugin.Author);
- if (Directory.Exists(newPluginPath))
+ PluginPair existingPlugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ID == plugin.ID);
+
+ if (existingPlugin != null)
{
- PluginMetadata existingPlugin = GetMetadataFromJson(newPluginPath);
- if (existingPlugin == null || existingPlugin.Name == null)
- {
- //maybe broken plugin, just delete it
- Directory.Delete(newPluginPath, true);
- }
- else
- {
content = string.Format(
"Do you want to update following plugin?\r\n\r\nName: {0}\r\nOld Version: {1}\r\nNew Version: {2}\r\nAuthor: {3}",
- plugin.Name, existingPlugin.Version, plugin.Version, plugin.Author);
- }
+ plugin.Name, existingPlugin.Metadata.Version, plugin.Version, plugin.Author);
}
MessageBoxResult result = MessageBox.Show(content, "Install plugin",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
- if (Directory.Exists(newPluginPath))
+ if (existingPlugin != null && Directory.Exists(existingPlugin.Metadata.PluginDirecotry))
{
- Directory.Delete(newPluginPath, true);
+ File.Create(Path.Combine(existingPlugin.Metadata.PluginDirecotry, "NeedDelete.txt")).Close();
}
+
UnZip(path, newPluginPath, true);
Directory.Delete(tempFoler, true);
- if (MainWindow.Initialized)
+ //exsiting plugins may be has loaded by application,
+ //if we try to delelte those kind of plugins, we will get a error that indicate the
+ //file is been used now.
+ //current solution is to restart wox. Ugly.
+ //if (MainWindow.Initialized)
+ //{
+ // Plugins.Init();
+ //}
+ if (MessageBox.Show("You have installed plugin " + plugin.Name + " successfully.\r\n Restart Wox to take effect?", "Install plugin",
+ MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
- Plugins.Init();
+ ProcessStartInfo Info = new ProcessStartInfo();
+ Info.Arguments = "/C ping 127.0.0.1 -n 1 && \"" +
+ Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wox.exe") + "\"";
+ Info.WindowStyle = ProcessWindowStyle.Hidden;
+ Info.CreateNoWindow = true;
+ Info.FileName = "cmd.exe";
+ Process.Start(Info);
+ App.Window.CloseApp();
}
-
- MessageBox.Show("You have installed plugin " + plugin.Name + " successfully.");
}
}
}
diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs
index 88eb589bd3..b91482f7f4 100644
--- a/Wox/MainWindow.xaml.cs
+++ b/Wox/MainWindow.xaml.cs
@@ -41,7 +41,6 @@ namespace Wox
private NotifyIcon notifyIcon;
private bool queryHasReturn;
private ToolTip toolTip = new ToolTip();
-
public MainWindow()
{
InitializeComponent();
@@ -420,8 +419,18 @@ namespace Wox
toolTip.IsOpen = true;
}
+ public void StartLoadingBar()
+ {
+ Dispatcher.Invoke(new Action(StartProgress));
+ }
+
+ public void StopLoadingBar()
+ {
+ Dispatcher.Invoke(new Action(StopProgress));
+ }
+
#endregion
-
+
}
}
\ No newline at end of file
diff --git a/Wox/PluginLoader/Plugins.cs b/Wox/PluginLoader/Plugins.cs
index 4b3361dc67..41d7033261 100644
--- a/Wox/PluginLoader/Plugins.cs
+++ b/Wox/PluginLoader/Plugins.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CSharp;
+using Wox.Helper;
using Wox.Plugin;
namespace Wox.PluginLoader
@@ -30,14 +31,21 @@ namespace Wox.PluginLoader
{
Plugins = plugins,
CurrentPluginMetadata = metadata,
- ChangeQuery = s => App.Window.ChangeQuery(s),
- CloseApp = App.Window.CloseApp,
- HideApp = App.Window.HideApp,
- ShowApp = () => App.Window.ShowApp(),
- ShowMsg = (title, subTitle, iconPath) => App.Window.ShowMsg(title, subTitle, iconPath),
- OpenSettingDialog = () => App.Window.OpenSettingDialog(),
- ShowCurrentResultItemTooltip = (msg) => App.Window.ShowCurrentResultItemTooltip(msg),
- ReloadPlugins = ()=> Init()
+ ChangeQuery = s => App.Window.Dispatcher.Invoke(new Action(() => App.Window.ChangeQuery(s))),
+ CloseApp = () => App.Window.Dispatcher.Invoke(new Action(() => App.Window.CloseApp())),
+ HideApp = () => App.Window.Dispatcher.Invoke(new Action(() => App.Window.HideApp())),
+ ShowApp = () => App.Window.Dispatcher.Invoke(new Action(() => App.Window.ShowApp())),
+ ShowMsg = (title, subTitle, iconPath) => App.Window.Dispatcher.Invoke(new Action(() =>
+ App.Window.ShowMsg(title, subTitle, iconPath))),
+ OpenSettingDialog = () => App.Window.Dispatcher.Invoke(new Action(() => App.Window.OpenSettingDialog())),
+ ShowCurrentResultItemTooltip = (msg) => App.Window.Dispatcher.Invoke(new Action(() => App.Window.ShowCurrentResultItemTooltip(msg))),
+ ReloadPlugins = () => App.Window.Dispatcher.Invoke(new Action(() => Init())),
+ InstallPlugin = (filePath) => App.Window.Dispatcher.Invoke(new Action(() =>
+ {
+ PluginInstaller.Install(filePath);
+ })),
+ StartLoadingBar = () => App.Window.Dispatcher.Invoke(new Action(() => App.Window.StartLoadingBar())),
+ StopLoadingBar = () => App.Window.Dispatcher.Invoke(new Action(() => App.Window.StopLoadingBar())),
}));
}
}
diff --git a/Wox/PluginLoader/PythonPluginWrapper.cs b/Wox/PluginLoader/PythonPluginWrapper.cs
index 4e2843eb26..a021f7796d 100644
--- a/Wox/PluginLoader/PythonPluginWrapper.cs
+++ b/Wox/PluginLoader/PythonPluginWrapper.cs
@@ -76,6 +76,7 @@ namespace Wox.PluginLoader
{
string json = null;
+ //if pythobn plugin folder name is chinese, here will deadlock.
IntPtr gs = PythonEngine.AcquireLock();
PyObject module = PythonEngine.ImportModule(moduleName);