mirror of
https://github.com/greenshot/greenshot
synced 2025-08-14 02:37:03 -07:00
Merged 1.2 into master
This commit is contained in:
commit
9eb4f37523
57 changed files with 1809 additions and 720 deletions
|
@ -57,30 +57,47 @@ namespace Greenshot.Controls {
|
|||
|
||||
if (e.Index > -1) {
|
||||
FontFamily fontFamily = Items[e.Index] as FontFamily;
|
||||
FontStyle fs = FontStyle.Regular;
|
||||
FontStyle fontStyle = FontStyle.Regular;
|
||||
if (!fontFamily.IsStyleAvailable(FontStyle.Regular)) {
|
||||
if (fontFamily.IsStyleAvailable(FontStyle.Bold)) {
|
||||
fs = FontStyle.Bold;
|
||||
fontStyle = FontStyle.Bold;
|
||||
} else if (fontFamily.IsStyleAvailable(FontStyle.Italic)) {
|
||||
fs = FontStyle.Italic;
|
||||
fontStyle = FontStyle.Italic;
|
||||
} else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout)) {
|
||||
fs = FontStyle.Strikeout;
|
||||
fontStyle = FontStyle.Strikeout;
|
||||
} else if (fontFamily.IsStyleAvailable(FontStyle.Underline)) {
|
||||
fs = FontStyle.Underline;
|
||||
fontStyle = FontStyle.Underline;
|
||||
}
|
||||
}
|
||||
using (Font font = new Font(fontFamily, this.Font.Size + 5, fs, GraphicsUnit.Pixel)) {
|
||||
// Make sure the text is visible by centering it in the line
|
||||
using(StringFormat stringFormat = new StringFormat()) {
|
||||
stringFormat.LineAlignment = StringAlignment.Center;
|
||||
e.Graphics.DrawString(fontFamily.Name, font, Brushes.Black, e.Bounds, stringFormat);
|
||||
}
|
||||
try {
|
||||
DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name);
|
||||
} catch {
|
||||
// If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular'
|
||||
DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name);
|
||||
}
|
||||
}
|
||||
// Uncomment this if you actually like the way the focus rectangle looks
|
||||
//e.DrawFocusRectangle ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to draw the string
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="fontFamily"></param>
|
||||
/// <param name="fontStyle"></param>
|
||||
/// <param name="bounds"></param>
|
||||
/// <param name="text"></param>
|
||||
private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text) {
|
||||
using (Font font = new Font(fontFamily, this.Font.Size + 5, fontStyle, GraphicsUnit.Pixel)) {
|
||||
// Make sure the text is visible by centering it in the line
|
||||
using (StringFormat stringFormat = new StringFormat()) {
|
||||
stringFormat.LineAlignment = StringAlignment.Center;
|
||||
graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
if (PropertyChanged != null) {
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("Text"));
|
||||
|
|
|
@ -135,7 +135,7 @@ namespace Greenshot.Destinations {
|
|||
string filepath = FilenameHelper.FillVariables(conf.OutputFilePath, false);
|
||||
try {
|
||||
fullPath = Path.Combine(filepath, filename);
|
||||
} catch (ArgumentException ae) {
|
||||
} catch (ArgumentException) {
|
||||
// configured filename or path not valid, show error message...
|
||||
LOG.InfoFormat("Generated path or filename not valid: {0}, {1}", filepath, filename);
|
||||
|
||||
|
|
|
@ -146,9 +146,6 @@ namespace Greenshot {
|
|||
// Only use double-buffering when we are NOT in a Terminal Server session
|
||||
DoubleBuffered = !isTerminalServerSession;
|
||||
|
||||
// Not needed for a Tool Window, but still for the task manager it's important
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
|
||||
// Use the self drawn image, first we create the background to be the backcolor (as we animate from this)
|
||||
gBitmap = ImageHelper.CreateEmpty(90, 90, PixelFormat.Format24bppRgb, BackColor, 96, 96);
|
||||
pictureBox1.Image = gBitmap;
|
||||
|
|
|
@ -31,8 +31,7 @@ namespace Greenshot.Forms {
|
|||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
InitializeComponent();
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
WindowDetails.ToForeground(Handle);
|
||||
ToFront = true;
|
||||
}
|
||||
|
||||
public BugReportForm(string bugText) : this() {
|
||||
|
|
2
Greenshot/Forms/CaptureForm.Designer.cs
generated
2
Greenshot/Forms/CaptureForm.Designer.cs
generated
|
@ -61,7 +61,7 @@ namespace Greenshot.Forms {
|
|||
this.Cursor = System.Windows.Forms.Cursors.Cross;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||
this.Name = "CaptureForm";
|
||||
this.ShowIcon = false;
|
||||
this.ShowIcon = true;
|
||||
this.ShowInTaskbar = false;
|
||||
this.TopMost = true;
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.CaptureFormKeyDown);
|
||||
|
|
|
@ -123,6 +123,7 @@ namespace Greenshot.Forms {
|
|||
LOG.Debug("Closing captureform");
|
||||
WindowDetails.UnregisterIgnoreHandle(Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This creates the capture form
|
||||
/// </summary>
|
||||
|
@ -130,7 +131,7 @@ namespace Greenshot.Forms {
|
|||
/// <param name="windows"></param>
|
||||
public CaptureForm(ICapture capture, List<WindowDetails> windows) {
|
||||
if (_currentForm != null) {
|
||||
LOG.Debug("Found currentForm, Closing already opened CaptureForm");
|
||||
LOG.Warn("Found currentForm, Closing already opened CaptureForm");
|
||||
_currentForm.Close();
|
||||
_currentForm = null;
|
||||
Application.DoEvents();
|
||||
|
@ -176,7 +177,7 @@ namespace Greenshot.Forms {
|
|||
ResumeLayout();
|
||||
|
||||
// Fix missing focus
|
||||
WindowDetails.ToForeground(Handle);
|
||||
ToFront = true;
|
||||
TopMost = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ namespace Greenshot.Forms {
|
|||
public DropShadowSettingsForm(DropShadowEffect effect) {
|
||||
this.effect = effect;
|
||||
InitializeComponent();
|
||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
||||
ShowSettings();
|
||||
}
|
||||
|
||||
|
|
|
@ -162,8 +162,6 @@ namespace Greenshot {
|
|||
}
|
||||
|
||||
private void updateUI() {
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
|
||||
// Disable access to the settings, for feature #3521446
|
||||
preferencesToolStripMenuItem.Visible = !coreConfiguration.DisableSettings;
|
||||
toolStripSeparator12.Visible = !coreConfiguration.DisableSettings;
|
||||
|
|
|
@ -270,6 +270,9 @@ namespace Greenshot {
|
|||
return;
|
||||
}
|
||||
|
||||
// BUG-1809: Add message filter, to filter out all the InputLangChanged messages which go to a target control with a handle > 32 bit.
|
||||
Application.AddMessageFilter(new WmInputLangChangeRequestFilter());
|
||||
|
||||
// From here on we continue starting Greenshot
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
@ -359,7 +362,6 @@ namespace Greenshot {
|
|||
throw;
|
||||
}
|
||||
notifyIcon.Icon = GreenshotResources.getGreenshotIcon();
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
|
||||
// Disable access to the settings, for feature #3521446
|
||||
contextmenu_settings.Visible = !_conf.DisableSettings;
|
||||
|
@ -508,14 +510,20 @@ namespace Greenshot {
|
|||
get {return contextMenu;}
|
||||
}
|
||||
|
||||
#region hotkeys
|
||||
protected override void WndProc(ref Message m) {
|
||||
if (HotkeyControl.HandleMessages(ref m)) {
|
||||
return;
|
||||
}
|
||||
base.WndProc(ref m);
|
||||
// BUG-1809 prevention, filter the InputLangChange messages
|
||||
if (WmInputLangChangeRequestFilter.PreFilterMessageExternal(ref m))
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
#region hotkeys
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to cleanly register a hotkey
|
||||
/// </summary>
|
||||
|
@ -1223,14 +1231,27 @@ namespace Greenshot {
|
|||
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
||||
Exception exceptionToLog = e.ExceptionObject as Exception;
|
||||
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
|
||||
LOG.Error(EnvironmentInfo.ExceptionToString(exceptionToLog));
|
||||
LOG.Error("Exception caught in the UnhandledException handler.");
|
||||
LOG.Error(exceptionText);
|
||||
if (exceptionText != null && exceptionText.Contains("InputLanguageChangedEventArgs"))
|
||||
{
|
||||
// Ignore for BUG-1809
|
||||
return;
|
||||
}
|
||||
new BugReportForm(exceptionText).ShowDialog();
|
||||
}
|
||||
|
||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
|
||||
Exception exceptionToLog = e.Exception;
|
||||
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
|
||||
LOG.Error(EnvironmentInfo.ExceptionToString(exceptionToLog));
|
||||
LOG.Error("Exception caught in the ThreadException handler.");
|
||||
LOG.Error(exceptionText);
|
||||
if (exceptionText != null && exceptionText.Contains("InputLanguageChangedEventArgs"))
|
||||
{
|
||||
// Ignore for BUG-1809
|
||||
return;
|
||||
}
|
||||
|
||||
new BugReportForm(exceptionText).ShowDialog();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace Greenshot.Forms {
|
|||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
InitializeComponent();
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
checkbox_dontaskagain.Checked = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace Greenshot.Forms {
|
|||
public ResizeSettingsForm(ResizeEffect effect) {
|
||||
this.effect = effect;
|
||||
InitializeComponent();
|
||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
||||
value_pixel = Language.GetString("editor_resize_pixel");
|
||||
value_percent = Language.GetString("editor_resize_percent");
|
||||
combobox_width.Items.Add(value_pixel);
|
||||
|
|
|
@ -57,7 +57,6 @@ namespace Greenshot {
|
|||
|
||||
protected override void OnLoad(EventArgs e) {
|
||||
base.OnLoad(e);
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
|
||||
// Fix for Vista/XP differences
|
||||
if (Environment.OSVersion.Version.Major >= 6) {
|
||||
|
|
|
@ -30,7 +30,6 @@ namespace Greenshot.Forms {
|
|||
public TornEdgeSettingsForm(TornEdgeEffect effect) {
|
||||
this.effect = effect;
|
||||
InitializeComponent();
|
||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
||||
ShowSettings();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
/*
|
||||
* Created by SharpDevelop.
|
||||
* User: jens
|
||||
* Date: 09.04.2012
|
||||
* Time: 19:24
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* To change this template use Tools | Options | Coding | Edit Standard Headers.
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin.Core;
|
||||
|
@ -28,7 +40,7 @@ namespace Greenshot.Help
|
|||
}
|
||||
|
||||
public static void LoadHelp() {
|
||||
string uri = findOnlineHelpUrl(Language.CurrentLanguage);
|
||||
string uri = FindOnlineHelpUrl(Language.CurrentLanguage);
|
||||
if(uri == null) {
|
||||
uri = Language.HelpFilePath;
|
||||
}
|
||||
|
@ -36,7 +48,7 @@ namespace Greenshot.Help
|
|||
}
|
||||
|
||||
/// <returns>URL of help file in selected ietf, or (if not present) default ietf, or null (if not present, too. probably indicating that there is no internet connection)</returns>
|
||||
private static string findOnlineHelpUrl(string currentIETF) {
|
||||
private static string FindOnlineHelpUrl(string currentIETF) {
|
||||
string ret = null;
|
||||
|
||||
string extHelpUrlForCurrrentIETF = EXT_HELP_URL;
|
||||
|
@ -45,12 +57,12 @@ namespace Greenshot.Help
|
|||
extHelpUrlForCurrrentIETF += currentIETF.ToLower() + "/";
|
||||
}
|
||||
|
||||
HttpStatusCode? httpStatusCode = getHttpStatus(extHelpUrlForCurrrentIETF);
|
||||
HttpStatusCode? httpStatusCode = GetHttpStatus(extHelpUrlForCurrrentIETF);
|
||||
if(httpStatusCode == HttpStatusCode.OK) {
|
||||
ret = extHelpUrlForCurrrentIETF;
|
||||
} else if(httpStatusCode != null && !extHelpUrlForCurrrentIETF.Equals(EXT_HELP_URL)) {
|
||||
LOG.DebugFormat("Localized online help not found at {0}, will try {1} as fallback", extHelpUrlForCurrrentIETF, EXT_HELP_URL);
|
||||
httpStatusCode = getHttpStatus(EXT_HELP_URL);
|
||||
httpStatusCode = GetHttpStatus(EXT_HELP_URL);
|
||||
if(httpStatusCode == HttpStatusCode.OK) {
|
||||
ret = EXT_HELP_URL;
|
||||
} else {
|
||||
|
@ -68,9 +80,9 @@ namespace Greenshot.Help
|
|||
/// </summary>
|
||||
/// <param name="url">URL for which the HTTP status is to be checked</param>
|
||||
/// <returns>An HTTP status code, or null if there is none (probably indicating that there is no internet connection available</returns>
|
||||
private static HttpStatusCode? getHttpStatus(string url) {
|
||||
private static HttpStatusCode? GetHttpStatus(string url) {
|
||||
try {
|
||||
HttpWebRequest req = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
HttpWebRequest req = NetworkHelper.CreateWebRequest(url);
|
||||
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
|
||||
return res.StatusCode;
|
||||
} catch(WebException e) {
|
||||
|
|
|
@ -967,7 +967,13 @@ namespace Greenshot.Helpers {
|
|||
//}
|
||||
|
||||
using (CaptureForm captureForm = new CaptureForm(_capture, _windows)) {
|
||||
DialogResult result = captureForm.ShowDialog();
|
||||
// Make sure the form is hidden after showing, even if an exception occurs, so all errors will be shown
|
||||
DialogResult result = DialogResult.Cancel;
|
||||
try {
|
||||
result = captureForm.ShowDialog(MainForm.Instance);
|
||||
} finally {
|
||||
captureForm.Hide();
|
||||
}
|
||||
if (result == DialogResult.OK) {
|
||||
_selectedCaptureWindow = captureForm.SelectedCaptureWindow;
|
||||
_captureRect = captureForm.CaptureRectangle;
|
||||
|
@ -975,11 +981,11 @@ namespace Greenshot.Helpers {
|
|||
if (_selectedCaptureWindow != null) {
|
||||
_capture.CaptureDetails.Title = _selectedCaptureWindow.Text;
|
||||
}
|
||||
|
||||
|
||||
if (_captureRect.Height > 0 && _captureRect.Width > 0) {
|
||||
// Take the captureRect, this already is specified as bitmap coordinates
|
||||
_capture.Crop(_captureRect);
|
||||
|
||||
|
||||
// save for re-capturing later and show recapture context menu option
|
||||
// Important here is that the location needs to be offsetted back to screen coordinates!
|
||||
Rectangle tmpRectangle = _captureRect;
|
||||
|
|
|
@ -18,30 +18,33 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using GreenshotPlugin.Core;
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Drawing;
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using log4net;
|
||||
|
||||
namespace Greenshot.Helpers {
|
||||
namespace Greenshot.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of EnvironmentInfo.
|
||||
/// </summary>
|
||||
public static class EnvironmentInfo {
|
||||
public static class EnvironmentInfo
|
||||
{
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(EnvironmentInfo));
|
||||
private static bool? isWindows = null;
|
||||
|
||||
public static bool IsWindows {
|
||||
get {
|
||||
if (isWindows.HasValue) {
|
||||
public static bool IsWindows
|
||||
{
|
||||
get
|
||||
{
|
||||
if (isWindows.HasValue)
|
||||
{
|
||||
return isWindows.Value;
|
||||
}
|
||||
isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win");
|
||||
|
@ -49,75 +52,104 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
}
|
||||
|
||||
public static bool IsNet45OrNewer() {
|
||||
public static bool IsNet45OrNewer()
|
||||
{
|
||||
// Class "ReflectionContext" exists from .NET 4.5 onwards.
|
||||
return Type.GetType("System.Reflection.ReflectionContext", false) != null;
|
||||
}
|
||||
|
||||
public static string EnvironmentToString(bool newline) {
|
||||
public static string EnvironmentToString(bool newline)
|
||||
{
|
||||
StringBuilder environment = new StringBuilder();
|
||||
environment.Append("Software version: " + Application.ProductVersion);
|
||||
if (IniConfig.IsPortable) {
|
||||
environment.Append(" Portable");
|
||||
environment.Append(" Portable");
|
||||
}
|
||||
environment.Append(" (" + OSInfo.Bits + " bit)");
|
||||
|
||||
if (newline) {
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.Append(".NET runtime version: " + Environment.Version);
|
||||
if (IsNet45OrNewer()) {
|
||||
if (IsNet45OrNewer())
|
||||
{
|
||||
environment.Append("+");
|
||||
|
||||
}
|
||||
if (newline) {
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
|
||||
|
||||
if (IsWindows) {
|
||||
if (newline) {
|
||||
if (IsWindows)
|
||||
{
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.Append(String.Format("OS: {0} {1} {2} (x{3}) {4}", OSInfo.Name, OSInfo.Edition, OSInfo.ServicePack, OSInfo.Bits, OSInfo.VersionString));
|
||||
if (newline) {
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
// Get some important information for fixing GDI related Problems
|
||||
environment.Append("GDI object count: " + User32.GetGuiResourcesGDICount());
|
||||
if (newline) {
|
||||
environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount());
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.Append("User object count: " + User32.GetGuiResourcesUserCount());
|
||||
} else {
|
||||
if (newline) {
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.Append("OS: " + Environment.OSVersion.Platform.ToString());
|
||||
environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount());
|
||||
}
|
||||
if (newline) {
|
||||
else
|
||||
{
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform);
|
||||
}
|
||||
if (newline)
|
||||
{
|
||||
environment.AppendLine();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
environment.Append(", ");
|
||||
}
|
||||
environment.Append("Surface count: " + Surface.Count);
|
||||
// TODO: Is this needed?
|
||||
// environment.AppendFormat("Surface count: {0}", Surface.Count);
|
||||
|
||||
return environment.ToString();
|
||||
}
|
||||
|
||||
public static string ExceptionToString(Exception ex) {
|
||||
public static string ExceptionToString(Exception ex)
|
||||
{
|
||||
if (ex == null)
|
||||
return "null\r\n";
|
||||
|
||||
|
@ -125,44 +157,54 @@ namespace Greenshot.Helpers {
|
|||
|
||||
report.AppendLine("Exception: " + ex.GetType().ToString());
|
||||
report.AppendLine("Message: " + ex.Message);
|
||||
if (ex.Data != null && ex.Data.Count > 0) {
|
||||
if (ex.Data != null && ex.Data.Count > 0)
|
||||
{
|
||||
report.AppendLine();
|
||||
report.AppendLine("Additional Information:");
|
||||
foreach (object key in ex.Data.Keys) {
|
||||
foreach (object key in ex.Data.Keys)
|
||||
{
|
||||
object data = ex.Data[key];
|
||||
if (data != null) {
|
||||
if (data != null)
|
||||
{
|
||||
report.AppendLine(key + " : " + data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ex is ExternalException) {
|
||||
if (ex is ExternalException)
|
||||
{
|
||||
// e.g. COMException
|
||||
report.AppendLine().AppendLine("ErrorCode: 0x" + (ex as ExternalException).ErrorCode.ToString("X"));
|
||||
}
|
||||
|
||||
report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace);
|
||||
|
||||
if (ex is ReflectionTypeLoadException) {
|
||||
if (ex is ReflectionTypeLoadException)
|
||||
{
|
||||
report.AppendLine().AppendLine("LoaderExceptions: ");
|
||||
foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions) {
|
||||
foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions)
|
||||
{
|
||||
report.AppendLine(cbE.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (ex.InnerException != null) {
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
report.AppendLine("--- InnerException: ---");
|
||||
report.AppendLine(ExceptionToString(ex.InnerException));
|
||||
}
|
||||
return report.ToString();
|
||||
}
|
||||
|
||||
public static string BuildReport(Exception exception) {
|
||||
public static string BuildReport(Exception exception)
|
||||
{
|
||||
StringBuilder exceptionText = new StringBuilder();
|
||||
exceptionText.AppendLine(EnvironmentToString(true));
|
||||
exceptionText.AppendLine(ExceptionToString(exception));
|
||||
exceptionText.AppendLine("Configuration dump:");
|
||||
using (TextWriter writer = new StringWriter(exceptionText)) {
|
||||
IniConfig.GetIniSection<CoreConfiguration>().Write(writer, true);
|
||||
using (TextWriter writer = new StringWriter(exceptionText))
|
||||
{
|
||||
// TODO: Create summary of properties
|
||||
//var iniConfig = IniConfig.Current.WriteToStreamAsync();
|
||||
}
|
||||
|
||||
return exceptionText.ToString();
|
||||
|
@ -173,13 +215,16 @@ namespace Greenshot.Helpers {
|
|||
/// Provides detailed information about the host operating system.
|
||||
/// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
|
||||
/// </summary>
|
||||
static public class OSInfo {
|
||||
static public class OSInfo
|
||||
{
|
||||
#region BITS
|
||||
/// <summary>
|
||||
/// Determines if the current application is 32 or 64-bit.
|
||||
/// </summary>
|
||||
static public int Bits {
|
||||
get {
|
||||
static public int Bits
|
||||
{
|
||||
get
|
||||
{
|
||||
return IntPtr.Size * 8;
|
||||
}
|
||||
}
|
||||
|
@ -190,9 +235,12 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the edition of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public string Edition {
|
||||
get {
|
||||
if (s_Edition != null) {
|
||||
static public string Edition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Edition != null)
|
||||
{
|
||||
return s_Edition; //***** RETURN *****//
|
||||
}
|
||||
|
||||
|
@ -202,22 +250,30 @@ namespace Greenshot.Helpers {
|
|||
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
||||
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
||||
|
||||
if (GetVersionEx(ref osVersionInfo)) {
|
||||
if (GetVersionEx(ref osVersionInfo))
|
||||
{
|
||||
int majorVersion = osVersion.Version.Major;
|
||||
int minorVersion = osVersion.Version.Minor;
|
||||
byte productType = osVersionInfo.wProductType;
|
||||
short suiteMask = osVersionInfo.wSuiteMask;
|
||||
|
||||
#region VERSION 4
|
||||
if (majorVersion == 4) {
|
||||
if (productType == VER_NT_WORKSTATION) {
|
||||
if (majorVersion == 4)
|
||||
{
|
||||
if (productType == VER_NT_WORKSTATION)
|
||||
{
|
||||
// Windows NT 4.0 Workstation
|
||||
edition = "Workstation";
|
||||
} else if (productType == VER_NT_SERVER) {
|
||||
if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) {
|
||||
}
|
||||
else if (productType == VER_NT_SERVER)
|
||||
{
|
||||
if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
|
||||
{
|
||||
// Windows NT 4.0 Server Enterprise
|
||||
edition = "Enterprise Server";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Windows NT 4.0 Server
|
||||
edition = "Standard Server";
|
||||
}
|
||||
|
@ -226,38 +282,60 @@ namespace Greenshot.Helpers {
|
|||
#endregion VERSION 4
|
||||
|
||||
#region VERSION 5
|
||||
else if (majorVersion == 5) {
|
||||
if (productType == VER_NT_WORKSTATION) {
|
||||
if ((suiteMask & VER_SUITE_PERSONAL) != 0) {
|
||||
else if (majorVersion == 5)
|
||||
{
|
||||
if (productType == VER_NT_WORKSTATION)
|
||||
{
|
||||
if ((suiteMask & VER_SUITE_PERSONAL) != 0)
|
||||
{
|
||||
// Windows XP Home Edition
|
||||
edition = "Home";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Windows XP / Windows 2000 Professional
|
||||
edition = "Professional";
|
||||
}
|
||||
} else if (productType == VER_NT_SERVER) {
|
||||
if (minorVersion == 0) {
|
||||
if ((suiteMask & VER_SUITE_DATACENTER) != 0) {
|
||||
}
|
||||
else if (productType == VER_NT_SERVER)
|
||||
{
|
||||
if (minorVersion == 0)
|
||||
{
|
||||
if ((suiteMask & VER_SUITE_DATACENTER) != 0)
|
||||
{
|
||||
// Windows 2000 Datacenter Server
|
||||
edition = "Datacenter Server";
|
||||
} else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) {
|
||||
}
|
||||
else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
|
||||
{
|
||||
// Windows 2000 Advanced Server
|
||||
edition = "Advanced Server";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Windows 2000 Server
|
||||
edition = "Server";
|
||||
}
|
||||
} else {
|
||||
if ((suiteMask & VER_SUITE_DATACENTER) != 0) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((suiteMask & VER_SUITE_DATACENTER) != 0)
|
||||
{
|
||||
// Windows Server 2003 Datacenter Edition
|
||||
edition = "Datacenter";
|
||||
} else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) {
|
||||
}
|
||||
else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
|
||||
{
|
||||
// Windows Server 2003 Enterprise Edition
|
||||
edition = "Enterprise";
|
||||
} else if ((suiteMask & VER_SUITE_BLADE) != 0) {
|
||||
}
|
||||
else if ((suiteMask & VER_SUITE_BLADE) != 0)
|
||||
{
|
||||
// Windows Server 2003 Web Edition
|
||||
edition = "Web Edition";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Windows Server 2003 Standard Edition
|
||||
edition = "Standard";
|
||||
}
|
||||
|
@ -267,10 +345,13 @@ namespace Greenshot.Helpers {
|
|||
#endregion VERSION 5
|
||||
|
||||
#region VERSION 6
|
||||
else if (majorVersion == 6) {
|
||||
else if (majorVersion == 6)
|
||||
{
|
||||
int ed;
|
||||
if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.wServicePackMajor, osVersionInfo.wServicePackMinor, out ed)) {
|
||||
switch (ed) {
|
||||
if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.wServicePackMajor, osVersionInfo.wServicePackMinor, out ed))
|
||||
{
|
||||
switch (ed)
|
||||
{
|
||||
case PRODUCT_BUSINESS:
|
||||
edition = "Business";
|
||||
break;
|
||||
|
@ -399,9 +480,12 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the name of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public string Name {
|
||||
get {
|
||||
if (s_Name != null) {
|
||||
static public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Name != null)
|
||||
{
|
||||
return s_Name; //***** RETURN *****//
|
||||
}
|
||||
|
||||
|
@ -411,27 +495,37 @@ namespace Greenshot.Helpers {
|
|||
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
||||
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
||||
|
||||
if (GetVersionEx(ref osVersionInfo)) {
|
||||
if (GetVersionEx(ref osVersionInfo))
|
||||
{
|
||||
int majorVersion = osVersion.Version.Major;
|
||||
int minorVersion = osVersion.Version.Minor;
|
||||
byte productType = osVersionInfo.wProductType;
|
||||
short suiteMask = osVersionInfo.wSuiteMask;
|
||||
switch (osVersion.Platform) {
|
||||
switch (osVersion.Platform)
|
||||
{
|
||||
case PlatformID.Win32Windows:
|
||||
if (majorVersion == 4) {
|
||||
if (majorVersion == 4)
|
||||
{
|
||||
string csdVersion = osVersionInfo.szCSDVersion;
|
||||
switch (minorVersion) {
|
||||
switch (minorVersion)
|
||||
{
|
||||
case 0:
|
||||
if (csdVersion == "B" || csdVersion == "C") {
|
||||
if (csdVersion == "B" || csdVersion == "C")
|
||||
{
|
||||
name = "Windows 95 OSR2";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "Windows 95";
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (csdVersion == "A") {
|
||||
if (csdVersion == "A")
|
||||
{
|
||||
name = "Windows 98 Second Edition";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "Windows 98";
|
||||
}
|
||||
break;
|
||||
|
@ -442,12 +536,14 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
case PlatformID.Win32NT:
|
||||
switch (majorVersion) {
|
||||
switch (majorVersion)
|
||||
{
|
||||
case 3:
|
||||
name = "Windows NT 3.51";
|
||||
break;
|
||||
case 4:
|
||||
switch (productType) {
|
||||
switch (productType)
|
||||
{
|
||||
case 1:
|
||||
name = "Windows NT 4.0";
|
||||
break;
|
||||
|
@ -457,12 +553,14 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (minorVersion) {
|
||||
switch (minorVersion)
|
||||
{
|
||||
case 0:
|
||||
name = "Windows 2000";
|
||||
break;
|
||||
case 1:
|
||||
switch (suiteMask) {
|
||||
switch (suiteMask)
|
||||
{
|
||||
case 0x0200:
|
||||
name = "Windows XP Professional";
|
||||
break;
|
||||
|
@ -472,7 +570,8 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (suiteMask) {
|
||||
switch (suiteMask)
|
||||
{
|
||||
case 0x0200:
|
||||
name = "Windows XP Professional x64";
|
||||
break;
|
||||
|
@ -496,9 +595,11 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (minorVersion) {
|
||||
switch (minorVersion)
|
||||
{
|
||||
case 0:
|
||||
switch (productType) {
|
||||
switch (productType)
|
||||
{
|
||||
case 3:
|
||||
name = "Windows Server 2008";
|
||||
break;
|
||||
|
@ -508,7 +609,8 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
case 1:
|
||||
switch (productType) {
|
||||
switch (productType)
|
||||
{
|
||||
case 3:
|
||||
name = "Windows Server 2008 R2";
|
||||
break;
|
||||
|
@ -520,8 +622,14 @@ namespace Greenshot.Helpers {
|
|||
case 2:
|
||||
name = "Windows 8";
|
||||
break;
|
||||
case 3:
|
||||
name = "Windows 8.1";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
name = "Windows 10";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -553,7 +661,8 @@ namespace Greenshot.Helpers {
|
|||
|
||||
#region OSVERSIONINFOEX
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct OSVERSIONINFOEX {
|
||||
private struct OSVERSIONINFOEX
|
||||
{
|
||||
public int dwOSVersionInfoSize;
|
||||
public int dwMajorVersion;
|
||||
public int dwMinorVersion;
|
||||
|
@ -629,14 +738,17 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the service pack information of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public string ServicePack {
|
||||
get {
|
||||
static public string ServicePack
|
||||
{
|
||||
get
|
||||
{
|
||||
string servicePack = String.Empty;
|
||||
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
||||
|
||||
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
||||
|
||||
if (GetVersionEx(ref osVersionInfo)) {
|
||||
if (GetVersionEx(ref osVersionInfo))
|
||||
{
|
||||
servicePack = osVersionInfo.szCSDVersion;
|
||||
}
|
||||
|
||||
|
@ -650,8 +762,10 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the build version number of the operating system running on this computer.
|
||||
/// </summary>
|
||||
public static int BuildVersion {
|
||||
get {
|
||||
public static int BuildVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.OSVersion.Version.Build;
|
||||
}
|
||||
}
|
||||
|
@ -662,8 +776,10 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the full version string of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public string VersionString {
|
||||
get {
|
||||
static public string VersionString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("{0}.{1} build {3} revision {2:X}", Environment.OSVersion.Version.Major, Environment.OSVersion.Version.Minor, Environment.OSVersion.Version.Revision, Environment.OSVersion.Version.Build);
|
||||
}
|
||||
}
|
||||
|
@ -673,8 +789,10 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the full version of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public Version Version {
|
||||
get {
|
||||
static public Version Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.OSVersion.Version;
|
||||
}
|
||||
}
|
||||
|
@ -685,8 +803,10 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the major version number of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public int MajorVersion {
|
||||
get {
|
||||
static public int MajorVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.OSVersion.Version.Major;
|
||||
}
|
||||
}
|
||||
|
@ -696,8 +816,10 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the minor version number of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public int MinorVersion {
|
||||
get {
|
||||
static public int MinorVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.OSVersion.Version.Minor;
|
||||
}
|
||||
}
|
||||
|
@ -707,12 +829,14 @@ namespace Greenshot.Helpers {
|
|||
/// <summary>
|
||||
/// Gets the revision version number of the operating system running on this computer.
|
||||
/// </summary>
|
||||
static public int RevisionVersion {
|
||||
get {
|
||||
static public int RevisionVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.OSVersion.Version.Revision;
|
||||
}
|
||||
}
|
||||
#endregion REVISION
|
||||
#endregion VERSION
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,14 +9,16 @@
|
|||
</asmv3:application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!--The ID below indicates app support for Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
<!--The ID below indicates app support for Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
<!--The ID below indicates app support for Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!--The ID below indicates app support for Windows 8.1 -->
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<!--Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
<!-- Set UAC level to "asInvoker" and disable registry virtualization -->
|
||||
|
|
|
@ -9,6 +9,26 @@ All details to our tickets can be found here: https://greenshot.atlassian.net
|
|||
|
||||
@DETAILVERSION@
|
||||
|
||||
Bugs Resolved:
|
||||
* BUG-1809: OverflowException when changing the windows input language
|
||||
* BUG-1835: Imgur: uploads were cancelled due to a timeout which was set too small
|
||||
* BUG-1833: Imgur: API-Key issues when using anonymous uploads
|
||||
* Github Pull 1: Fixed error calling external command. Thanks to viper3400
|
||||
|
||||
|
||||
1.2.6.7-359dcf3 RELEASE
|
||||
|
||||
Bugs Resolved:
|
||||
* BUG-1769: Switched to OAuth 2 for Picasa Authentication, OAuth 1.x will be terminated as of 20th of April 2015.
|
||||
* BUG-1770: Fix problems when a font doesn't want to draw itself.
|
||||
* Bug 1774: Problems logging in to Box.com
|
||||
|
||||
Features add:
|
||||
* FEATURE-838: Added support for dragging an image from google image search results directly into the editor.
|
||||
|
||||
|
||||
1.2.5.19-RELEASE-63412d3b9e29
|
||||
|
||||
Bugs Resolved:
|
||||
* BUG-1578, BUG-1657: by default, Imgur plugin no longer passes title and filename to Imgur (for new installations, existing configuration files won't be affected)
|
||||
* BUG-1655: Greenshot uses the default proxy, even if the "use default proxy" check-box is not checked.
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Windows.Forms;
|
||||
using Greenshot.IniFile;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
|
||||
namespace GreenshotBoxPlugin {
|
||||
/// <summary>
|
||||
|
@ -38,10 +40,37 @@ namespace GreenshotBoxPlugin {
|
|||
public bool AfterUploadLinkToClipBoard;
|
||||
|
||||
[IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")]
|
||||
public bool UseSharedLink;
|
||||
public bool UseSharedLink {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[IniProperty("FolderId", Description = "Folder ID to upload to, only change if you know what you are doing!", DefaultValue = "0")]
|
||||
public string FolderId {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[IniProperty("BoxToken", Description = "Token.", DefaultValue = "")]
|
||||
public string BoxToken;
|
||||
[IniProperty("RefreshToken", Description = "Box authorization refresh Token", Encrypted = true)]
|
||||
public string RefreshToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public string AccessToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public DateTimeOffset AccessTokenExpires {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A form for token
|
||||
|
|
|
@ -18,16 +18,14 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using GreenshotPlugin.Core;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Greenshot.IniFile;
|
||||
using GreenshotPlugin.Controls;
|
||||
using GreenshotPlugin.Core;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace GreenshotBoxPlugin {
|
||||
|
||||
|
@ -37,101 +35,24 @@ namespace GreenshotBoxPlugin {
|
|||
public static class BoxUtils {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxUtils));
|
||||
private static readonly BoxConfiguration Config = IniConfig.GetIniSection<BoxConfiguration>();
|
||||
private const string RedirectUri = "https://www.box.com/home/";
|
||||
private const string UploadFileUri = "https://upload.box.com/api/2.0/files/content";
|
||||
private const string AuthorizeUri = "https://www.box.com/api/oauth2/authorize";
|
||||
private const string TokenUri = "https://www.box.com/api/oauth2/token";
|
||||
private const string FilesUri = "https://www.box.com/api/2.0/files/{0}";
|
||||
|
||||
private static bool Authorize() {
|
||||
string authorizeUrl = string.Format("{0}?client_id={1}&response_type=code&state=dropboxplugin&redirect_uri={2}", AuthorizeUri, BoxCredentials.ClientId, RedirectUri);
|
||||
|
||||
OAuthLoginForm loginForm = new OAuthLoginForm("Box Authorize", new Size(1060, 600), authorizeUrl, RedirectUri);
|
||||
loginForm.ShowDialog();
|
||||
if (!loginForm.isOk) {
|
||||
return false;
|
||||
}
|
||||
var callbackParameters = loginForm.CallbackParameters;
|
||||
if (callbackParameters == null || !callbackParameters.ContainsKey("code")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string authorizationResponse = PostAndReturn(new Uri(TokenUri), string.Format("grant_type=authorization_code&code={0}&client_id={1}&client_secret={2}", callbackParameters["code"], BoxCredentials.ClientId, BoxCredentials.ClientSecret));
|
||||
var authorization = JsonSerializer.Deserialize<Authorization>(authorizationResponse);
|
||||
|
||||
Config.BoxToken = authorization.AccessToken;
|
||||
IniConfig.Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download a url response as string
|
||||
/// </summary>
|
||||
/// <param name="url">An Uri to specify the download location</param>
|
||||
/// <param name="postMessage"></param>
|
||||
/// <returns>string with the file content</returns>
|
||||
public static string PostAndReturn(Uri url, string postMessage) {
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url);
|
||||
webRequest.Method = "POST";
|
||||
webRequest.KeepAlive = true;
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
byte[] data = Encoding.UTF8.GetBytes(postMessage);
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
}
|
||||
return NetworkHelper.GetResponse(webRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload parameters by post
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns>response</returns>
|
||||
public static string HttpPost(string url, IDictionary<string, object> parameters) {
|
||||
var webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
webRequest.Method = "POST";
|
||||
webRequest.KeepAlive = true;
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
webRequest.Headers.Add("Authorization", "Bearer " + Config.BoxToken);
|
||||
NetworkHelper.WriteMultipartFormData(webRequest, parameters);
|
||||
|
||||
return NetworkHelper.GetResponse(webRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload file by PUT
|
||||
/// Put string
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="settings">OAuth2Settings</param>
|
||||
/// <returns>response</returns>
|
||||
public static string HttpPut(string url, string content) {
|
||||
var webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
webRequest.Method = "PUT";
|
||||
webRequest.KeepAlive = true;
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
webRequest.Headers.Add("Authorization", "Bearer " + Config.BoxToken);
|
||||
public static string HttpPut(string url, string content, OAuth2Settings settings) {
|
||||
var webRequest= OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.PUT, url, settings);
|
||||
|
||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
}
|
||||
return NetworkHelper.GetResponse(webRequest);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get REST request
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns>response</returns>
|
||||
public static string HttpGet(string url) {
|
||||
var webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
webRequest.Method = "GET";
|
||||
webRequest.KeepAlive = true;
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
webRequest.Headers.Add("Authorization", "Bearer " + Config.BoxToken);
|
||||
return NetworkHelper.GetResponse(webRequest);
|
||||
return NetworkHelper.GetResponseAsString(webRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -143,45 +64,52 @@ namespace GreenshotBoxPlugin {
|
|||
/// <param name="filename">Filename of box upload</param>
|
||||
/// <returns>url to uploaded image</returns>
|
||||
public static string UploadToBox(SurfaceContainer image, string title, string filename) {
|
||||
while (true) {
|
||||
const string folderId = "0";
|
||||
if (string.IsNullOrEmpty(Config.BoxToken)) {
|
||||
if (!Authorize()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the OAuth2Settings
|
||||
OAuth2Settings settings = new OAuth2Settings();
|
||||
|
||||
settings.AuthUrlPattern = "https://app.box.com/api/oauth2/authorize?client_id={ClientId}&response_type=code&state={State}&redirect_uri={RedirectUrl}";
|
||||
settings.TokenUrl = "https://api.box.com/oauth2/token";
|
||||
settings.CloudServiceName = "Box";
|
||||
settings.ClientId = BoxCredentials.ClientId;
|
||||
settings.ClientSecret = BoxCredentials.ClientSecret;
|
||||
settings.RedirectUrl = "https://www.box.com/home/";
|
||||
settings.BrowserSize = new Size(1060, 600);
|
||||
settings.AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser;
|
||||
|
||||
// Copy the settings from the config, which is kept in memory and on the disk
|
||||
settings.RefreshToken = Config.RefreshToken;
|
||||
settings.AccessToken = Config.AccessToken;
|
||||
settings.AccessTokenExpires = Config.AccessTokenExpires;
|
||||
|
||||
try {
|
||||
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, UploadFileUri, settings);
|
||||
IDictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("filename", image);
|
||||
parameters.Add("parent_id", folderId);
|
||||
parameters.Add("file", image);
|
||||
parameters.Add("parent_id", Config.FolderId);
|
||||
|
||||
var response = "";
|
||||
try {
|
||||
response = HttpPost(UploadFileUri, parameters);
|
||||
} catch (WebException ex) {
|
||||
if (ex.Status == WebExceptionStatus.ProtocolError) {
|
||||
Config.BoxToken = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
NetworkHelper.WriteMultipartFormData(webRequest, parameters);
|
||||
|
||||
var response = NetworkHelper.GetResponseAsString(webRequest);
|
||||
|
||||
LOG.DebugFormat("Box response: {0}", response);
|
||||
|
||||
// Check if the token is wrong
|
||||
if ("wrong auth token".Equals(response)) {
|
||||
Config.BoxToken = null;
|
||||
IniConfig.Save();
|
||||
continue;
|
||||
}
|
||||
var upload = JsonSerializer.Deserialize<Upload>(response);
|
||||
if (upload == null || upload.Entries == null || upload.Entries.Count == 0) return null;
|
||||
|
||||
if (Config.UseSharedLink) {
|
||||
string filesResponse = HttpPut(string.Format(FilesUri, upload.Entries[0].Id), "{\"shared_link\": {\"access\": \"open\"}}");
|
||||
string filesResponse = HttpPut(string.Format(FilesUri, upload.Entries[0].Id), "{\"shared_link\": {\"access\": \"open\"}}", settings);
|
||||
var file = JsonSerializer.Deserialize<FileEntry>(filesResponse);
|
||||
return file.SharedLink.Url;
|
||||
}
|
||||
return string.Format("http://www.box.com/files/0/f/0/1/f_{0}", upload.Entries[0].Id);
|
||||
} finally {
|
||||
// Copy the settings back to the config, so they are stored.
|
||||
Config.RefreshToken = settings.RefreshToken;
|
||||
Config.AccessToken = settings.AccessToken;
|
||||
Config.AccessTokenExpires = settings.AccessTokenExpires;
|
||||
Config.IsDirty = true;
|
||||
IniConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,6 @@ namespace GreenshotBoxPlugin {
|
|||
InitializeComponent();
|
||||
AcceptButton = buttonOK;
|
||||
CancelButton = buttonCancel;
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using GreenshotDropboxPlugin.Forms;
|
||||
|
@ -39,7 +40,6 @@ namespace GreenshotDropboxPlugin {
|
|||
InitializeComponent();
|
||||
AcceptButton = buttonOK;
|
||||
CancelButton = buttonCancel;
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace ExternalCommand {
|
|||
if (config.OutputToClipboard) {
|
||||
ClipboardHelper.SetClipboardData(output);
|
||||
}
|
||||
if (uriMatches != null && uriMatches.Count >= 0) {
|
||||
if (uriMatches != null && uriMatches.Count > 0) {
|
||||
exportInformation.Uri = uriMatches[0].Groups[1].Value;
|
||||
LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
|
||||
if (config.UriToClipboard) {
|
||||
|
@ -134,10 +134,10 @@ namespace ExternalCommand {
|
|||
exportInformation.ExportMade = false;
|
||||
exportInformation.ErrorMessage = error;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
|
||||
} catch (Exception ex) {
|
||||
exportInformation.ExportMade = false;
|
||||
exportInformation.ErrorMessage = ex.Message;
|
||||
LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace ExternalCommand {
|
|||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
InitializeComponent();
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
AcceptButton = buttonOk;
|
||||
CancelButton = buttonCancel;
|
||||
UpdateView();
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace ExternalCommand {
|
|||
|
||||
public SettingsFormDetail(string commando) {
|
||||
InitializeComponent();
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
AcceptButton = buttonOk;
|
||||
CancelButton = buttonCancel;
|
||||
this.commando = commando;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace GreenshotFlickrPlugin {
|
|||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
InitializeComponent();
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
CancelButton = buttonCancel;
|
||||
AcceptButton = buttonOK;
|
||||
}
|
||||
|
|
|
@ -18,13 +18,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace GreenshotImgurPlugin {
|
||||
/// <summary>
|
||||
/// This class is needed for design-time resolving of the language files
|
||||
/// </summary>
|
||||
public class ImgurForm : GreenshotPlugin.Controls.GreenshotForm {
|
||||
public class ImgurForm : GreenshotForm {
|
||||
public ImgurForm() : base() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ namespace GreenshotImgurPlugin
|
|||
this.finishedButton.TabIndex = 11;
|
||||
this.finishedButton.Text = "Finished";
|
||||
this.finishedButton.UseVisualStyleBackColor = true;
|
||||
this.finishedButton.Click += new System.EventHandler(this.FinishedButtonClick);
|
||||
//
|
||||
// clipboardButton
|
||||
//
|
||||
|
|
|
@ -53,7 +53,6 @@ namespace GreenshotImgurPlugin {
|
|||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
InitializeComponent();
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
AcceptButton = finishedButton;
|
||||
CancelButton = finishedButton;
|
||||
// Init sorting
|
||||
|
@ -168,6 +167,11 @@ namespace GreenshotImgurPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
private void FinishedButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
this.Hide();
|
||||
}
|
||||
|
||||
private void OpenButtonClick(object sender, EventArgs e) {
|
||||
if (listview_imgur_uploads.SelectedItems != null && listview_imgur_uploads.SelectedItems.Count > 0) {
|
||||
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) {
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace GreenshotImgurPlugin {
|
|||
InitializeComponent();
|
||||
CancelButton = buttonCancel;
|
||||
AcceptButton = buttonOK;
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
|
||||
ImgurUtils.LoadHistory();
|
||||
|
||||
|
|
|
@ -30,9 +30,11 @@ namespace GreenshotImgurPlugin {
|
|||
/// </summary>
|
||||
[IniSection("Imgur", Description="Greenshot Imgur Plugin configuration")]
|
||||
public class ImgurConfiguration : IniSection {
|
||||
[IniProperty("ImgurApiUrl", Description="Url to Imgur system.", DefaultValue="http://api.imgur.com/2")]
|
||||
[IniProperty("ImgurApiUrl", Description="Url to Imgur system.", DefaultValue= "http://api.imgur.com/2")]
|
||||
public string ImgurApiUrl;
|
||||
|
||||
[IniProperty("ImgurApi3Url", Description = "Url to Imgur system.", DefaultValue = "https://api.imgur.com/3")]
|
||||
public string ImgurApi3Url;
|
||||
|
||||
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
|
||||
public OutputFormat UploadFormat;
|
||||
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
|
||||
|
|
|
@ -143,10 +143,15 @@ namespace GreenshotImgurPlugin
|
|||
try {
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("hash");
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("id");
|
||||
if(nodes.Count > 0) {
|
||||
imgurInfo.Hash = nodes.Item(0).InnerText;
|
||||
}
|
||||
nodes = doc.GetElementsByTagName("hash");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Hash = nodes.Item(0).InnerText;
|
||||
}
|
||||
nodes = doc.GetElementsByTagName("deletehash");
|
||||
if(nodes.Count > 0) {
|
||||
imgurInfo.DeleteHash = nodes.Item(0).InnerText;
|
||||
|
@ -161,16 +166,41 @@ namespace GreenshotImgurPlugin
|
|||
}
|
||||
nodes = doc.GetElementsByTagName("datetime");
|
||||
if(nodes.Count > 0) {
|
||||
imgurInfo.Timestamp = DateTime.Parse(nodes.Item(0).InnerText);
|
||||
try
|
||||
{
|
||||
imgurInfo.Timestamp = DateTime.Parse(nodes.Item(0).InnerText);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Version 3 has seconds since Epoch
|
||||
double secondsSince;
|
||||
if (double.TryParse(nodes.Item(0).InnerText, out secondsSince))
|
||||
{
|
||||
var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
nodes = doc.GetElementsByTagName("original");
|
||||
if(nodes.Count > 0) {
|
||||
imgurInfo.Original = nodes.Item(0).InnerText;
|
||||
}
|
||||
// Version 3 API only has Link
|
||||
nodes = doc.GetElementsByTagName("link");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Original = nodes.Item(0).InnerText;
|
||||
}
|
||||
nodes = doc.GetElementsByTagName("imgur_page");
|
||||
if(nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Page = nodes.Item(0).InnerText;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Version 3 doesn't have a page link in the response
|
||||
imgurInfo.Page = string.Format("http://imgur.com/{0}", imgurInfo.Hash);
|
||||
}
|
||||
nodes = doc.GetElementsByTagName("small_square");
|
||||
if(nodes.Count > 0) {
|
||||
imgurInfo.SmallSquare = nodes.Item(0).InnerText;
|
||||
|
|
|
@ -31,14 +31,15 @@ namespace GreenshotImgurPlugin {
|
|||
/// <summary>
|
||||
/// Description of ImgurUtils.
|
||||
/// </summary>
|
||||
public class ImgurUtils {
|
||||
public static class ImgurUtils {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ImgurUtils));
|
||||
private const string IMGUR_ANONYMOUS_API_KEY = "8116a978913f3cf5dfc8e1117a055056";
|
||||
private const string IMGUR_ANONYMOUS_API_KEY = "60e8838e21d6b66";
|
||||
private const string SMALL_URL_PATTERN = "http://i.imgur.com/{0}s.png";
|
||||
private static ImgurConfiguration config = IniConfig.GetIniSection<ImgurConfiguration>();
|
||||
|
||||
private ImgurUtils() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the complete history of the imgur uploads, with the corresponding information
|
||||
/// </summary>
|
||||
public static void LoadHistory() {
|
||||
if (config.runtimeImgurHistory.Count == config.ImgurUploadHistory.Count) {
|
||||
return;
|
||||
|
@ -57,9 +58,9 @@ namespace GreenshotImgurPlugin {
|
|||
continue;
|
||||
}
|
||||
try {
|
||||
ImgurInfo imgurInfo = ImgurUtils.RetrieveImgurInfo(hash, config.ImgurUploadHistory[hash]);
|
||||
ImgurInfo imgurInfo = RetrieveImgurInfo(hash, config.ImgurUploadHistory[hash]);
|
||||
if (imgurInfo != null) {
|
||||
ImgurUtils.RetrieveImgurThumbnail(imgurInfo);
|
||||
RetrieveImgurThumbnail(imgurInfo);
|
||||
config.runtimeImgurHistory.Add(hash, imgurInfo);
|
||||
} else {
|
||||
LOG.DebugFormat("Deleting not found ImgUr {0} from config.", hash);
|
||||
|
@ -90,6 +91,14 @@ namespace GreenshotImgurPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to make sure Imgur knows from where the upload comes.
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
private static void SetClientId(HttpWebRequest webRequest) {
|
||||
webRequest.Headers.Add("Authorization", "Client-ID " + IMGUR_ANONYMOUS_API_KEY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do the actual upload to Imgur
|
||||
/// For more details on the available parameters, see: http://api.imgur.com/resources_anon
|
||||
|
@ -113,11 +122,12 @@ namespace GreenshotImgurPlugin {
|
|||
string responseString = null;
|
||||
if (config.AnonymousAccess) {
|
||||
// add key, we only use the other parameters for the AnonymousAccess
|
||||
otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(config.ImgurApiUrl + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters));
|
||||
webRequest.Method = "POST";
|
||||
webRequest.ContentType = "image/" + outputSettings.Format.ToString();
|
||||
//otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST);
|
||||
webRequest.ContentType = "image/" + outputSettings.Format;
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
|
||||
SetClientId(webRequest);
|
||||
try {
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
|
||||
|
@ -127,7 +137,7 @@ namespace GreenshotImgurPlugin {
|
|||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
||||
responseString = reader.ReadToEnd();
|
||||
}
|
||||
LogCredits(response);
|
||||
LogRateLimitInfo(response);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.Error("Upload to imgur gave an exeption: ", ex);
|
||||
|
@ -174,34 +184,43 @@ namespace GreenshotImgurPlugin {
|
|||
return ImgurInfo.ParseResponse(responseString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the thumbnail of an imgur image
|
||||
/// </summary>
|
||||
/// <param name="imgurInfo"></param>
|
||||
public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo) {
|
||||
if (imgurInfo.SmallSquare == null) {
|
||||
LOG.Warn("Imgur URL was null, not retrieving thumbnail.");
|
||||
return;
|
||||
}
|
||||
LOG.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare);
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(imgurInfo.SmallSquare);
|
||||
webRequest.Method = "GET";
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SMALL_URL_PATTERN, imgurInfo.Hash), HTTPMethod.GET);
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
|
||||
SetClientId(webRequest);
|
||||
using (WebResponse response = webRequest.GetResponse()) {
|
||||
LogCredits(response);
|
||||
LogRateLimitInfo(response);
|
||||
Stream responseStream = response.GetResponseStream();
|
||||
imgurInfo.Image = Image.FromStream(responseStream);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve information on an imgur image
|
||||
/// </summary>
|
||||
/// <param name="hash"></param>
|
||||
/// <param name="deleteHash"></param>
|
||||
/// <returns>ImgurInfo</returns>
|
||||
public static ImgurInfo RetrieveImgurInfo(string hash, string deleteHash) {
|
||||
string url = config.ImgurApiUrl + "/image/" + hash;
|
||||
LOG.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url);
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
webRequest.Method = "GET";
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
SetClientId(webRequest);
|
||||
string responseString;
|
||||
try {
|
||||
using (WebResponse response = webRequest.GetResponse()) {
|
||||
LogCredits(response);
|
||||
LogRateLimitInfo(response);
|
||||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
||||
responseString = reader.ReadToEnd();
|
||||
}
|
||||
|
@ -220,20 +239,21 @@ namespace GreenshotImgurPlugin {
|
|||
return imgurInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete an imgur image, this is done by specifying the delete hash
|
||||
/// </summary>
|
||||
/// <param name="imgurInfo"></param>
|
||||
public static void DeleteImgurImage(ImgurInfo imgurInfo) {
|
||||
LOG.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash);
|
||||
|
||||
try {
|
||||
string url = config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash;
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
|
||||
//webRequest.Method = "DELETE";
|
||||
webRequest.Method = "GET";
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
|
||||
SetClientId(webRequest);
|
||||
string responseString;
|
||||
using (WebResponse response = webRequest.GetResponse()) {
|
||||
LogCredits(response);
|
||||
LogRateLimitInfo(response);
|
||||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
||||
responseString = reader.ReadToEnd();
|
||||
}
|
||||
|
@ -252,17 +272,42 @@ namespace GreenshotImgurPlugin {
|
|||
config.ImgurUploadHistory.Remove(imgurInfo.Hash);
|
||||
imgurInfo.Image = null;
|
||||
}
|
||||
|
||||
private static void LogCredits(WebResponse response) {
|
||||
try {
|
||||
int credits = 0;
|
||||
if (int.TryParse(response.Headers["X-RateLimit-Remaining"], out credits)) {
|
||||
config.Credits = credits;
|
||||
|
||||
/// <summary>
|
||||
/// Helper for logging
|
||||
/// </summary>
|
||||
/// <param name="nameValues"></param>
|
||||
/// <param name="key"></param>
|
||||
private static void LogHeader(IDictionary<string, string> nameValues, string key) {
|
||||
if (nameValues.ContainsKey(key)) {
|
||||
LOG.InfoFormat("key={0}", nameValues[key]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log the current rate-limit information
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
private static void LogRateLimitInfo(WebResponse response) {
|
||||
IDictionary<string, string> nameValues = new Dictionary<string, string>();
|
||||
foreach (string key in response.Headers.AllKeys) {
|
||||
if (!nameValues.ContainsKey(key)) {
|
||||
nameValues.Add(key, response.Headers[key]);
|
||||
}
|
||||
LOG.InfoFormat("X-RateLimit-Limit={0}", response.Headers["X-RateLimit-Limit"]);
|
||||
LOG.InfoFormat("X-RateLimit-Remaining={0}", response.Headers["X-RateLimit-Remaining"]);
|
||||
|
||||
} catch {}
|
||||
}
|
||||
LogHeader(nameValues, "X-RateLimit-Limit");
|
||||
LogHeader(nameValues, "X-RateLimit-Remaining");
|
||||
LogHeader(nameValues, "X-RateLimit-UserLimit");
|
||||
LogHeader(nameValues, "X-RateLimit-UserRemaining");
|
||||
LogHeader(nameValues, "X-RateLimit-UserReset");
|
||||
LogHeader(nameValues, "X-RateLimit-ClientLimit");
|
||||
LogHeader(nameValues, "X-RateLimit-ClientRemaining");
|
||||
|
||||
// Update the credits in the config, this is shown in a form
|
||||
int credits = 0;
|
||||
if (nameValues.ContainsKey("X-RateLimit-Remaining") && int.TryParse(nameValues["X-RateLimit-Remaining"], out credits)) {
|
||||
config.Credits = credits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace GreenshotJiraPlugin {
|
|||
InitializeComponent();
|
||||
AcceptButton = buttonOK;
|
||||
CancelButton = buttonCancel;
|
||||
Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace GreenshotOCR {
|
||||
/// <summary>
|
||||
/// This class is needed for design-time resolving of the language files
|
||||
/// </summary>
|
||||
public class OCRForm : GreenshotPlugin.Controls.GreenshotForm {
|
||||
public class OCRForm : GreenshotForm {
|
||||
public OCRForm() : base() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace GreenshotOCR {
|
|||
InitializeComponent();
|
||||
AcceptButton = buttonOK;
|
||||
CancelButton = buttonCancel;
|
||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
||||
|
||||
comboBox_languages.Items.Clear();
|
||||
int index=0;
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace GreenshotPhotobucketPlugin {
|
|||
InitializeComponent();
|
||||
AcceptButton = buttonOK;
|
||||
CancelButton = buttonCancel;
|
||||
Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace GreenshotPicasaPlugin {
|
|||
InitializeComponent();
|
||||
CancelButton = buttonCancel;
|
||||
AcceptButton = buttonOK;
|
||||
Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
using System.Windows.Forms;
|
||||
using Greenshot.IniFile;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
|
||||
namespace GreenshotPicasaPlugin {
|
||||
/// <summary>
|
||||
|
@ -36,11 +37,45 @@ namespace GreenshotPicasaPlugin {
|
|||
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Picasa link to clipboard.", DefaultValue = "true")]
|
||||
public bool AfterUploadLinkToClipBoard;
|
||||
|
||||
[IniProperty("PicasaToken", Description = "Picasa Token", Encrypted = true)]
|
||||
public string PicasaToken;
|
||||
[IniProperty("AddFilename", Description = "Is the filename passed on to Picasa", DefaultValue = "False")]
|
||||
public bool AddFilename {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[IniProperty("PicasaTokenSecret", Description = "PicasaTokenSecret", Encrypted = true)]
|
||||
public string PicasaTokenSecret;
|
||||
[IniProperty("UploadUser", Description = "The picasa user to upload to", DefaultValue = "default")]
|
||||
public string UploadUser {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[IniProperty("UploadAlbum", Description = "The picasa album to upload to", DefaultValue = "default")]
|
||||
public string UploadAlbum {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[IniProperty("RefreshToken", Description = "Picasa authorization refresh Token", Encrypted = true)]
|
||||
public string RefreshToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public string AccessToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public DateTimeOffset AccessTokenExpires {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A form for token
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace GreenshotPicasaPlugin {
|
|||
/// You can set your own values here
|
||||
/// </summary>
|
||||
public static class PicasaCredentials {
|
||||
public static string ConsumerKey = "@credentials_picasa_consumer_key@";
|
||||
public static string ConsumerSecret = "@credentials_picasa_consumer_secret@";
|
||||
public static string ClientId = "@credentials_picasa_consumer_key@";
|
||||
public static string ClientSecret = "@credentials_picasa_consumer_secret@";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,25 +17,25 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Xml;
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
|
||||
namespace GreenshotPicasaPlugin {
|
||||
/// <summary>
|
||||
/// Description of PicasaUtils.
|
||||
/// </summary>
|
||||
public class PicasaUtils {
|
||||
private const string GoogleAccountUri = "https://www.google.com/accounts/";
|
||||
public static class PicasaUtils {
|
||||
private const string PicasaScope = "https://picasaweb.google.com/data/";
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PicasaUtils));
|
||||
private static readonly PicasaConfiguration Config = IniConfig.GetIniSection<PicasaConfiguration>();
|
||||
|
||||
private PicasaUtils() {
|
||||
}
|
||||
private const string AuthUrl = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}&scope=" + PicasaScope;
|
||||
private const string TokenUrl = "https://www.googleapis.com/oauth2/v3/token";
|
||||
private const string UploadUrl = "https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}";
|
||||
|
||||
/// <summary>
|
||||
/// Do the actual upload to Picasa
|
||||
|
@ -46,46 +46,46 @@ namespace GreenshotPicasaPlugin {
|
|||
/// <param name="filename"></param>
|
||||
/// <returns>PicasaResponse</returns>
|
||||
public static string UploadToPicasa(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
|
||||
OAuthSession oAuth = new OAuthSession(PicasaCredentials.ConsumerKey, PicasaCredentials.ConsumerSecret);
|
||||
oAuth.BrowserSize = new Size(1020, 590);
|
||||
oAuth.AccessTokenUrl = GoogleAccountUri + "OAuthGetAccessToken";
|
||||
oAuth.AuthorizeUrl = GoogleAccountUri + "OAuthAuthorizeToken";
|
||||
oAuth.RequestTokenUrl = GoogleAccountUri + "OAuthGetRequestToken";
|
||||
oAuth.LoginTitle = "Picasa authorization";
|
||||
oAuth.Token = Config.PicasaToken;
|
||||
oAuth.TokenSecret = Config.PicasaTokenSecret;
|
||||
oAuth.RequestTokenParameters.Add("scope", "https://picasaweb.google.com/data/");
|
||||
oAuth.RequestTokenParameters.Add("xoauth_displayname", "Greenshot");
|
||||
if (string.IsNullOrEmpty(oAuth.Token)) {
|
||||
if (!oAuth.Authorize()) {
|
||||
return null;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(oAuth.Token)) {
|
||||
Config.PicasaToken = oAuth.Token;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
|
||||
Config.PicasaTokenSecret = oAuth.TokenSecret;
|
||||
}
|
||||
IniConfig.Save();
|
||||
}
|
||||
// Fill the OAuth2Settings
|
||||
OAuth2Settings settings = new OAuth2Settings();
|
||||
settings.AuthUrlPattern = AuthUrl;
|
||||
settings.TokenUrl = TokenUrl;
|
||||
settings.CloudServiceName = "Picasa";
|
||||
settings.ClientId = PicasaCredentials.ClientId;
|
||||
settings.ClientSecret = PicasaCredentials.ClientSecret;
|
||||
settings.AuthorizeMode = OAuth2AuthorizeMode.LocalServer;
|
||||
|
||||
// Copy the settings from the config, which is kept in memory and on the disk
|
||||
settings.RefreshToken = Config.RefreshToken;
|
||||
settings.AccessToken = Config.AccessToken;
|
||||
settings.AccessTokenExpires = Config.AccessTokenExpires;
|
||||
|
||||
try {
|
||||
IDictionary<string, string> headers = new Dictionary<string, string>();
|
||||
headers.Add("slug", OAuthSession.UrlEncode3986(filename));
|
||||
string response = oAuth.MakeOAuthRequest(HTTPMethod.POST, "https://picasaweb.google.com/data/feed/api/user/default/albumid/default", headers, null, null, new SurfaceContainer(surfaceToUpload, outputSettings, filename));
|
||||
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings);
|
||||
if (Config.AddFilename) {
|
||||
webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename));
|
||||
}
|
||||
SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
|
||||
container.Upload(webRequest);
|
||||
|
||||
string response = NetworkHelper.GetResponseAsString(webRequest);
|
||||
|
||||
return ParseResponse(response);
|
||||
} catch (Exception ex) {
|
||||
LOG.Error("Upload error: ", ex);
|
||||
throw;
|
||||
} finally {
|
||||
if (!string.IsNullOrEmpty(oAuth.Token)) {
|
||||
Config.PicasaToken = oAuth.Token;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
|
||||
Config.PicasaTokenSecret = oAuth.TokenSecret;
|
||||
}
|
||||
// Copy the settings back to the config, so they are stored.
|
||||
Config.RefreshToken = settings.RefreshToken;
|
||||
Config.AccessToken = settings.AccessToken;
|
||||
Config.AccessTokenExpires = settings.AccessTokenExpires;
|
||||
Config.IsDirty = true;
|
||||
IniConfig.Save();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the upload URL from the response
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <returns></returns>
|
||||
public static string ParseResponse(string response) {
|
||||
if (response == null) {
|
||||
return null;
|
||||
|
|
|
@ -18,17 +18,20 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using Greenshot.IniFile;
|
||||
using log4net;
|
||||
|
||||
namespace GreenshotPlugin.Controls {
|
||||
/// <summary>
|
||||
/// Extend this Form to have the possibility for animations on your form
|
||||
/// </summary>
|
||||
public class AnimatingForm : GreenshotForm {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(AnimatingForm));
|
||||
private const int DEFAULT_VREFRESH = 60;
|
||||
private int vRefresh = 0;
|
||||
private Timer timer = null;
|
||||
|
@ -110,7 +113,11 @@ namespace GreenshotPlugin.Controls {
|
|||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void timer_Tick(object sender, EventArgs e) {
|
||||
Animate();
|
||||
try {
|
||||
Animate();
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn("An exception occured while animating:", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -38,11 +38,11 @@ namespace GreenshotPlugin.Controls {
|
|||
protected static CoreConfiguration coreConfiguration;
|
||||
private static IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
|
||||
private IComponentChangeService m_changeService;
|
||||
private bool isDesignModeLanguageSet = false;
|
||||
private bool applyLanguageManually = false;
|
||||
private bool storeFieldsManually = false;
|
||||
private IDictionary<string, Control> designTimeControls;
|
||||
private IDictionary<string, ToolStripItem> designTimeToolStripItems;
|
||||
private bool _isDesignModeLanguageSet = false;
|
||||
private bool _applyLanguageManually = false;
|
||||
private bool _storeFieldsManually = false;
|
||||
private IDictionary<string, Control> _designTimeControls;
|
||||
private IDictionary<string, ToolStripItem> _designTimeToolStripItems;
|
||||
|
||||
static GreenshotForm() {
|
||||
if (!IsInDesignMode) {
|
||||
|
@ -68,29 +68,37 @@ namespace GreenshotPlugin.Controls {
|
|||
|
||||
protected bool ManualLanguageApply {
|
||||
get {
|
||||
return applyLanguageManually;
|
||||
return _applyLanguageManually;
|
||||
}
|
||||
set {
|
||||
applyLanguageManually = value;
|
||||
_applyLanguageManually = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool ManualStoreFields {
|
||||
get {
|
||||
return storeFieldsManually;
|
||||
return _storeFieldsManually;
|
||||
}
|
||||
set {
|
||||
storeFieldsManually = value;
|
||||
_storeFieldsManually = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When this is set, the form will be brought to the foreground as soon as it is shown.
|
||||
/// </summary>
|
||||
protected bool ToFront {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Code to initialize the language etc during design time
|
||||
/// </summary>
|
||||
protected void InitializeForDesigner() {
|
||||
if (DesignMode) {
|
||||
designTimeControls = new Dictionary<string, Control>();
|
||||
designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
|
||||
_designTimeControls = new Dictionary<string, Control>();
|
||||
_designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
|
||||
try {
|
||||
ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
|
||||
|
||||
|
@ -119,8 +127,8 @@ namespace GreenshotPlugin.Controls {
|
|||
/// <param name="e"></param>
|
||||
protected override void OnPaint(PaintEventArgs e) {
|
||||
if (DesignMode) {
|
||||
if (!isDesignModeLanguageSet) {
|
||||
isDesignModeLanguageSet = true;
|
||||
if (!_isDesignModeLanguageSet) {
|
||||
_isDesignModeLanguageSet = true;
|
||||
try {
|
||||
ApplyLanguage();
|
||||
} catch (Exception) {
|
||||
|
@ -131,8 +139,11 @@ namespace GreenshotPlugin.Controls {
|
|||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e) {
|
||||
// Every GreenshotForm should have it's default icon
|
||||
// And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
if (!DesignMode) {
|
||||
if (!applyLanguageManually) {
|
||||
if (!_applyLanguageManually) {
|
||||
ApplyLanguage();
|
||||
}
|
||||
FillFields();
|
||||
|
@ -145,12 +156,23 @@ namespace GreenshotPlugin.Controls {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the form is visible, if this is wanted
|
||||
/// </summary>
|
||||
/// <param name="e">EventArgs</param>
|
||||
protected override void OnShown(EventArgs e) {
|
||||
base.OnShown(e);
|
||||
if (ToFront) {
|
||||
WindowDetails.ToForeground(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// check if the form was closed with an OK, if so store the values in the GreenshotControls
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnClosed(EventArgs e) {
|
||||
if (!DesignMode && !storeFieldsManually) {
|
||||
if (!DesignMode && !_storeFieldsManually) {
|
||||
if (DialogResult == DialogResult.OK) {
|
||||
LOG.Info("Form was closed with OK: storing field values.");
|
||||
StoreFields();
|
||||
|
@ -230,17 +252,17 @@ namespace GreenshotPlugin.Controls {
|
|||
if (ce.Component != null && ((IComponent)ce.Component).Site != null) {
|
||||
Control control = ce.Component as Control;
|
||||
if (control != null) {
|
||||
if (!designTimeControls.ContainsKey(control.Name)) {
|
||||
designTimeControls.Add(control.Name, control);
|
||||
if (!_designTimeControls.ContainsKey(control.Name)) {
|
||||
_designTimeControls.Add(control.Name, control);
|
||||
} else {
|
||||
designTimeControls[control.Name] = control;
|
||||
_designTimeControls[control.Name] = control;
|
||||
}
|
||||
} else if (ce.Component is ToolStripItem) {
|
||||
ToolStripItem item = ce.Component as ToolStripItem;
|
||||
if (!designTimeControls.ContainsKey(item.Name)) {
|
||||
designTimeToolStripItems.Add(item.Name, item);
|
||||
if (!_designTimeControls.ContainsKey(item.Name)) {
|
||||
_designTimeToolStripItems.Add(item.Name, item);
|
||||
} else {
|
||||
designTimeToolStripItems[item.Name] = item;
|
||||
_designTimeToolStripItems[item.Name] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,10 +382,10 @@ namespace GreenshotPlugin.Controls {
|
|||
}
|
||||
|
||||
if (DesignMode) {
|
||||
foreach (Control designControl in designTimeControls.Values) {
|
||||
foreach (Control designControl in _designTimeControls.Values) {
|
||||
ApplyLanguage(designControl);
|
||||
}
|
||||
foreach (ToolStripItem designToolStripItem in designTimeToolStripItems.Values) {
|
||||
foreach (ToolStripItem designToolStripItem in _designTimeToolStripItems.Values) {
|
||||
ApplyLanguage(designToolStripItem);
|
||||
}
|
||||
}
|
||||
|
@ -413,7 +435,7 @@ namespace GreenshotPlugin.Controls {
|
|||
if (section != null) {
|
||||
IniValue iniValue = null;
|
||||
if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue)) {
|
||||
LOG.WarnFormat("Wrong property '{0}' configured for field '{1}'",configBindable.PropertyName,field.Name);
|
||||
LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'",configBindable.PropertyName,field.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
44
GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs
generated
44
GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs
generated
|
@ -44,37 +44,37 @@ namespace GreenshotPlugin.Controls {
|
|||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
this.addressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.browser = new ExtendedWebBrowser();
|
||||
this._addressTextBox = new System.Windows.Forms.TextBox();
|
||||
this._browser = new ExtendedWebBrowser();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// addressTextBox
|
||||
// _addressTextBox
|
||||
//
|
||||
this.addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
|
||||
this.addressTextBox.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.addressTextBox.Enabled = false;
|
||||
this.addressTextBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.addressTextBox.Name = "addressTextBox";
|
||||
this.addressTextBox.Size = new System.Drawing.Size(595, 20);
|
||||
this.addressTextBox.TabIndex = 3;
|
||||
this.addressTextBox.TabStop = false;
|
||||
this._addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
|
||||
this._addressTextBox.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this._addressTextBox.Enabled = false;
|
||||
this._addressTextBox.Location = new System.Drawing.Point(0, 0);
|
||||
this._addressTextBox.Name = "addressTextBox";
|
||||
this._addressTextBox.Size = new System.Drawing.Size(595, 20);
|
||||
this._addressTextBox.TabIndex = 3;
|
||||
this._addressTextBox.TabStop = false;
|
||||
//
|
||||
// browser
|
||||
// _browser
|
||||
//
|
||||
this.browser.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.browser.Location = new System.Drawing.Point(0, 20);
|
||||
this.browser.MinimumSize = new System.Drawing.Size(100, 100);
|
||||
this.browser.Name = "browser";
|
||||
this.browser.Size = new System.Drawing.Size(595, 295);
|
||||
this.browser.TabIndex = 4;
|
||||
this._browser.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this._browser.Location = new System.Drawing.Point(0, 20);
|
||||
this._browser.MinimumSize = new System.Drawing.Size(100, 100);
|
||||
this._browser.Name = "browser";
|
||||
this._browser.Size = new System.Drawing.Size(595, 295);
|
||||
this._browser.TabIndex = 4;
|
||||
//
|
||||
// OAuthLoginForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(595, 315);
|
||||
this.Controls.Add(this.browser);
|
||||
this.Controls.Add(this.addressTextBox);
|
||||
this.Controls.Add(this._browser);
|
||||
this.Controls.Add(this._addressTextBox);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "OAuthLoginForm";
|
||||
|
@ -85,8 +85,8 @@ namespace GreenshotPlugin.Controls {
|
|||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox addressTextBox;
|
||||
private ExtendedWebBrowser browser;
|
||||
private System.Windows.Forms.TextBox _addressTextBox;
|
||||
private ExtendedWebBrowser _browser;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,62 +35,74 @@ namespace GreenshotPlugin.Controls {
|
|||
/// </summary>
|
||||
public partial class OAuthLoginForm : Form {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm));
|
||||
private string callbackUrl = null;
|
||||
private IDictionary<string, string> callbackParameters = null;
|
||||
private string _callbackUrl = null;
|
||||
private IDictionary<string, string> _callbackParameters = null;
|
||||
|
||||
public IDictionary<string, string> CallbackParameters {
|
||||
get { return callbackParameters; }
|
||||
get {
|
||||
return _callbackParameters;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isOk {
|
||||
public bool IsOk {
|
||||
get {
|
||||
return DialogResult == DialogResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) {
|
||||
this.callbackUrl = callbackUrl;
|
||||
_callbackUrl = callbackUrl;
|
||||
InitializeComponent();
|
||||
ClientSize = size;
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
Text = browserTitle;
|
||||
addressTextBox.Text = authorizationLink;
|
||||
_addressTextBox.Text = authorizationLink;
|
||||
|
||||
// The script errors are suppressed by using the ExtendedWebBrowser
|
||||
browser.ScriptErrorsSuppressed = false;
|
||||
browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
|
||||
browser.Navigate(new Uri(authorizationLink));
|
||||
_browser.ScriptErrorsSuppressed = false;
|
||||
_browser.DocumentCompleted += Browser_DocumentCompleted;
|
||||
_browser.Navigated += Browser_Navigated;
|
||||
_browser.Navigating += Browser_Navigating;
|
||||
_browser.Navigate(new Uri(authorizationLink));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the form is visible
|
||||
/// </summary>
|
||||
/// <param name="e">EventArgs</param>
|
||||
protected override void OnShown(EventArgs e) {
|
||||
base.OnShown(e);
|
||||
WindowDetails.ToForeground(Handle);
|
||||
}
|
||||
|
||||
private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
|
||||
LOG.DebugFormat("document completed with url: {0}", browser.Url);
|
||||
checkUrl();
|
||||
}
|
||||
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
|
||||
LOG.DebugFormat("Navigating to url: {0}", browser.Url);
|
||||
addressTextBox.Text = e.Url.ToString();
|
||||
private void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
|
||||
LOG.DebugFormat("document completed with url: {0}", _browser.Url);
|
||||
CheckUrl();
|
||||
}
|
||||
|
||||
private void browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
|
||||
LOG.DebugFormat("Navigated to url: {0}", browser.Url);
|
||||
checkUrl();
|
||||
private void Browser_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
|
||||
LOG.DebugFormat("Navigating to url: {0}", _browser.Url);
|
||||
_addressTextBox.Text = e.Url.ToString();
|
||||
}
|
||||
|
||||
private void checkUrl() {
|
||||
if (browser.Url.ToString().StartsWith(callbackUrl)) {
|
||||
string queryParams = browser.Url.Query;
|
||||
private void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
|
||||
LOG.DebugFormat("Navigated to url: {0}", _browser.Url);
|
||||
CheckUrl();
|
||||
}
|
||||
|
||||
private void CheckUrl() {
|
||||
if (_browser.Url.ToString().StartsWith(_callbackUrl)) {
|
||||
string queryParams = _browser.Url.Query;
|
||||
if (queryParams.Length > 0) {
|
||||
queryParams = NetworkHelper.UrlDecode(queryParams);
|
||||
//Store the Token and Token Secret
|
||||
callbackParameters = NetworkHelper.ParseQueryString(queryParams);
|
||||
_callbackParameters = NetworkHelper.ParseQueryString(queryParams);
|
||||
}
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
private void addressTextBox_KeyPress(object sender, KeyPressEventArgs e) {
|
||||
private void AddressTextBox_KeyPress(object sender, KeyPressEventArgs e) {
|
||||
//Cancel the key press so the user can't enter a new url
|
||||
e.Handled = true;
|
||||
}
|
||||
|
|
|
@ -41,14 +41,13 @@ namespace GreenshotPlugin.Controls {
|
|||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
InitializeComponent();
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
|
||||
checkBox_reduceColors.Checked = Settings.ReduceColors;
|
||||
trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
||||
trackBarJpegQuality.Value = Settings.JPGQuality;
|
||||
textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
||||
textBoxJpegQuality.Text = Settings.JPGQuality.ToString();
|
||||
WindowDetails.ToForeground(Handle);
|
||||
ToFront = true;
|
||||
}
|
||||
|
||||
void Button_okClick(object sender, EventArgs e) {
|
||||
|
|
|
@ -291,7 +291,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
[IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "10")]
|
||||
[IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
||||
public int WebRequestTimeout;
|
||||
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
||||
public int WebRequestReadWriteTimeout;
|
||||
|
@ -407,6 +407,17 @@ namespace GreenshotPlugin.Core {
|
|||
return base.PreCheckValue(propertyName, propertyValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called before writing the configuration
|
||||
/// </summary>
|
||||
public override void BeforeSave() {
|
||||
try {
|
||||
// Store version, this can be used later to fix settings after an update
|
||||
LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called after reading the configuration, so eventually some corrections can be made
|
||||
/// </summary>
|
||||
|
@ -498,8 +509,8 @@ namespace GreenshotPlugin.Core {
|
|||
OutputFileReduceColorsTo = 256;
|
||||
}
|
||||
|
||||
if (WebRequestTimeout < 1) {
|
||||
WebRequestTimeout = 10;
|
||||
if (WebRequestTimeout <= 10) {
|
||||
WebRequestTimeout = 100;
|
||||
}
|
||||
if (WebRequestReadWriteTimeout < 1) {
|
||||
WebRequestReadWriteTimeout = 100;
|
||||
|
|
|
@ -33,6 +33,17 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// HTTP Method to make sure we have the correct method
|
||||
/// </summary>
|
||||
public enum HTTPMethod {
|
||||
GET,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
HEAD
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Description of NetworkHelper.
|
||||
/// </summary>
|
||||
|
@ -54,11 +65,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <param name="uri">An Uri to specify the download location</param>
|
||||
/// <returns>string with the file content</returns>
|
||||
public static string GetAsString(Uri uri) {
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = "GET";
|
||||
webRequest.KeepAlive = true;
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
return GetResponse(webRequest);
|
||||
return GetResponseAsString(CreateWebRequest(uri));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -86,6 +93,26 @@ namespace GreenshotPlugin.Core {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the uri into a memorystream, without catching exceptions
|
||||
/// </summary>
|
||||
/// <param name="url">Of an image</param>
|
||||
/// <returns>MemoryStream which is already seeked to 0</returns>
|
||||
public static MemoryStream GetAsMemoryStream(string url) {
|
||||
HttpWebRequest request = CreateWebRequest(url);
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
using (Stream responseStream = response.GetResponseStream()) {
|
||||
if (responseStream != null) {
|
||||
responseStream.CopyTo(memoryStream);
|
||||
}
|
||||
// Make sure it can be used directly
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
return memoryStream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the uri to Bitmap
|
||||
/// </summary>
|
||||
|
@ -93,15 +120,27 @@ namespace GreenshotPlugin.Core {
|
|||
/// <returns>Bitmap</returns>
|
||||
public static Image DownloadImage(string url) {
|
||||
try {
|
||||
HttpWebRequest request = CreateWebRequest(url);
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (request.HaveResponse) {
|
||||
using (Stream responseStream = response.GetResponseStream()) {
|
||||
if (responseStream != null) {
|
||||
using (Image image = Image.FromStream(responseStream)) {
|
||||
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||
string content;
|
||||
using (MemoryStream memoryStream = GetAsMemoryStream(url)) {
|
||||
try {
|
||||
using (Image image = Image.FromStream(memoryStream)) {
|
||||
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
} catch (Exception) {
|
||||
// If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
|
||||
using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true)) {
|
||||
content = streamReader.ReadLine();
|
||||
}
|
||||
Regex imageUrlRegex = new Regex(@"(http|https)://.*(\.png|\.gif|\.jpg|\.tiff|\.jpeg|\.bmp)");
|
||||
Match match = imageUrlRegex.Match(content);
|
||||
if (match.Success) {
|
||||
using (MemoryStream memoryStream2 = GetAsMemoryStream(match.Value)) {
|
||||
using (Image image = Image.FromStream(memoryStream2)) {
|
||||
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -111,14 +150,36 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request, eventually with proxy
|
||||
/// Helper method to create a web request with a lot of default settings
|
||||
/// </summary>
|
||||
/// <param name="uri">string with uri to connect to</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(string uri) {
|
||||
return CreateWebRequest(new Uri(uri));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request with a lot of default settings
|
||||
/// </summary>
|
||||
/// <param name="uri">string with uri to connect to</param>
|
||||
/// /// <param name="method">Method to use</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) {
|
||||
return CreateWebRequest(new Uri(uri), method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request with a lot of default settings
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri with uri to connect to</param>
|
||||
/// <param name="method">Method to use</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) {
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = method.ToString();
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request, eventually with proxy
|
||||
/// </summary>
|
||||
|
@ -132,6 +193,10 @@ namespace GreenshotPlugin.Core {
|
|||
// BUG-1655: Fix that Greenshot always uses the default proxy even if the "use default proxy" checkbox is unset
|
||||
webRequest.Proxy = null;
|
||||
}
|
||||
// Make sure the default credentials are available
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
|
||||
// Allow redirect, this is usually needed so that we don't get a problem when a service moves
|
||||
webRequest.AllowAutoRedirect = true;
|
||||
// Set default timeouts
|
||||
webRequest.Timeout = Config.WebRequestTimeout*1000;
|
||||
|
@ -320,19 +385,57 @@ namespace GreenshotPlugin.Core {
|
|||
string footer = "\r\n--" + boundary + "--\r\n";
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Post the parameters "x-www-form-urlencoded"
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary<string, object> parameters) {
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
string urlEncoded = NetworkHelper.GenerateQueryParameters(parameters);
|
||||
|
||||
byte[] data = Encoding.UTF8.GetBytes(urlEncoded);
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log the headers of the WebResponse, if IsDebugEnabled
|
||||
/// </summary>
|
||||
/// <param name="response">WebResponse</param>
|
||||
private static void DebugHeaders(WebResponse response) {
|
||||
if (!LOG.IsDebugEnabled) {
|
||||
return;
|
||||
}
|
||||
LOG.DebugFormat("Debug information on the response from {0} :", response.ResponseUri);
|
||||
foreach (string key in response.Headers.AllKeys) {
|
||||
LOG.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the web response.
|
||||
/// </summary>
|
||||
/// <param name="webRequest">The request object.</param>
|
||||
/// <returns>The response data.</returns>
|
||||
/// TODO: This method should handle the StatusCode better!
|
||||
public static string GetResponse(HttpWebRequest webRequest) {
|
||||
public static string GetResponseAsString(HttpWebRequest webRequest) {
|
||||
return GetResponseAsString(webRequest, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) {
|
||||
string responseData = null;
|
||||
try {
|
||||
HttpWebResponse response = (HttpWebResponse) webRequest.GetResponse();
|
||||
LOG.InfoFormat("Response status: {0}", response.StatusCode);
|
||||
bool isHttpError = (int) response.StatusCode >= 300;
|
||||
DebugHeaders(response);
|
||||
Stream responseStream = response.GetResponseStream();
|
||||
if (responseStream != null) {
|
||||
using (StreamReader reader = new StreamReader(responseStream, true)) {
|
||||
|
@ -348,7 +451,13 @@ namespace GreenshotPlugin.Core {
|
|||
LOG.ErrorFormat("HTTP error {0}", response.StatusCode);
|
||||
using (Stream responseStream = response.GetResponseStream()) {
|
||||
if (responseStream != null) {
|
||||
LOG.ErrorFormat("Content: {0}", new StreamReader(responseStream, true).ReadToEnd());
|
||||
using (StreamReader streamReader = new StreamReader(responseStream, true)) {
|
||||
string errorContent = streamReader.ReadToEnd();
|
||||
if (alsoReturnContentOnError) {
|
||||
return errorContent;
|
||||
}
|
||||
LOG.ErrorFormat("Content: {0}", errorContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -367,7 +476,7 @@ namespace GreenshotPlugin.Core {
|
|||
public static DateTime GetLastModified(Uri uri) {
|
||||
try {
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = "HEAD";
|
||||
webRequest.Method = HTTPMethod.HEAD.ToString();
|
||||
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||
LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
|
||||
return webResponse.LastModified;
|
||||
|
|
|
@ -19,30 +19,198 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin.Controls;
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using GreenshotPlugin.Controls;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using log4net;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// Provides a predefined set of algorithms that are supported officially by the protocol
|
||||
/// Provides a predefined set of algorithms that are supported officially by the OAuth 1.x protocol
|
||||
/// </summary>
|
||||
public enum OAuthSignatureTypes {
|
||||
HMACSHA1,
|
||||
PLAINTEXT,
|
||||
RSASHA1
|
||||
}
|
||||
|
||||
public enum HTTPMethod { GET, POST, PUT, DELETE };
|
||||
|
||||
/// <summary>
|
||||
/// Specify the autorize mode that is used to get the token from the cloud service.
|
||||
/// </summary>
|
||||
public enum OAuth2AuthorizeMode {
|
||||
Unknown, // Will give an exception, caller needs to specify another value
|
||||
LocalServer, // Will specify a redirect URL to http://localhost:port/authorize, while having a HttpListener
|
||||
MonitorTitle, // Not implemented yet: Will monitor for title changes
|
||||
Pin, // Not implemented yet: Will ask the user to enter the shown PIN
|
||||
EmbeddedBrowser // Will open into an embedded _browser (OAuthLoginForm), and catch the redirect
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Settings for the OAuth 2 protocol
|
||||
/// </summary>
|
||||
public class OAuth2Settings {
|
||||
public OAuth2Settings() {
|
||||
AdditionalAttributes = new Dictionary<string, string>();
|
||||
// Create a default state
|
||||
State = Guid.NewGuid().ToString();
|
||||
AuthorizeMode = OAuth2AuthorizeMode.Unknown;
|
||||
}
|
||||
|
||||
public OAuth2AuthorizeMode AuthorizeMode {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the name of the cloud service, so it can be used in window titles, logs etc
|
||||
/// </summary>
|
||||
public string CloudServiceName {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the size of the embedded Browser, if using this
|
||||
/// </summary>
|
||||
public Size BrowserSize {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OAuth 2 client id
|
||||
/// </summary>
|
||||
public string ClientId {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OAuth 2 client secret
|
||||
/// </summary>
|
||||
public string ClientSecret {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OAuth 2 state, this is something that is passed to the server, is not processed but returned back to the client.
|
||||
/// e.g. a correlation ID
|
||||
/// Default this is filled with a new Guid
|
||||
/// </summary>
|
||||
public string State {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The autorization URL where the values of this class can be "injected"
|
||||
/// </summary>
|
||||
public string AuthUrlPattern {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get formatted Auth url (this will call a FormatWith(this) on the AuthUrlPattern
|
||||
/// </summary>
|
||||
public string FormattedAuthUrl {
|
||||
get {
|
||||
return AuthUrlPattern.FormatWith(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The URL to get a Token
|
||||
/// </summary>
|
||||
public string TokenUrl {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the redirect URL, in some implementations this is automatically set (LocalServerCodeReceiver)
|
||||
/// In some implementations this could be e.g. urn:ietf:wg:oauth:2.0:oob or urn:ietf:wg:oauth:2.0:oob:auto
|
||||
/// </summary>
|
||||
public string RedirectUrl {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bearer token for accessing OAuth 2 services
|
||||
/// </summary>
|
||||
public string AccessToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expire time for the AccessToken, this this time (-60 seconds) is passed a new AccessToken needs to be generated with the RefreshToken
|
||||
/// </summary>
|
||||
public DateTimeOffset AccessTokenExpires {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the access token is expired.
|
||||
/// Important "side-effect": if true is returned the AccessToken will be set to null!
|
||||
/// </summary>
|
||||
public bool IsAccessTokenExpired {
|
||||
get {
|
||||
bool expired = true;
|
||||
if (!string.IsNullOrEmpty(AccessToken) && AccessTokenExpires != null) {
|
||||
expired = DateTimeOffset.Now.AddSeconds(60) > AccessTokenExpires;
|
||||
}
|
||||
// Make sure the token is not usable
|
||||
if (expired) {
|
||||
AccessToken = null;
|
||||
}
|
||||
return expired;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Token used to get a new Access Token
|
||||
/// </summary>
|
||||
public string RefreshToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Put anything in here which is needed for the OAuth 2 implementation of this specific service but isn't generic, e.g. for Google there is a "scope"
|
||||
/// </summary>
|
||||
public IDictionary<string, string> AdditionalAttributes {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This contains the code returned from the authorization, but only shortly after it was received.
|
||||
/// It will be cleared as soon as it was used.
|
||||
/// </summary>
|
||||
public string Code {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An OAuth 1 session object
|
||||
/// </summary>
|
||||
public class OAuthSession {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthSession));
|
||||
protected const string OAUTH_VERSION = "1.0";
|
||||
|
@ -102,7 +270,7 @@ namespace GreenshotPlugin.Core {
|
|||
private readonly string _consumerKey;
|
||||
private readonly string _consumerSecret;
|
||||
|
||||
// default browser size
|
||||
// default _browser size
|
||||
private Size _browserSize = new Size(864, 587);
|
||||
private string _loginTitle = "Authorize Greenshot access";
|
||||
|
||||
|
@ -339,7 +507,7 @@ namespace GreenshotPlugin.Core {
|
|||
LOG.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink);
|
||||
OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(LoginTitle, BrowserSize, AuthorizationLink, CallbackUrl);
|
||||
oAuthLoginForm.ShowDialog();
|
||||
if (oAuthLoginForm.isOk) {
|
||||
if (oAuthLoginForm.IsOk) {
|
||||
if (oAuthLoginForm.CallbackParameters != null) {
|
||||
string tokenValue;
|
||||
if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_TOKEN_KEY, out tokenValue)) {
|
||||
|
@ -672,11 +840,9 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
// Create webrequest
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestURL);
|
||||
webRequest.Method = method.ToString();
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestURL, method);
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
webRequest.UserAgent = _userAgent;
|
||||
webRequest.Timeout = 100000;
|
||||
|
||||
if (UseHTTPHeadersForAuthorization && authHeader != null) {
|
||||
LOG.DebugFormat("Authorization: OAuth {0}", authHeader);
|
||||
|
@ -720,7 +886,7 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
string responseData;
|
||||
try {
|
||||
responseData = NetworkHelper.GetResponse(webRequest);
|
||||
responseData = NetworkHelper.GetResponseAsString(webRequest);
|
||||
LOG.DebugFormat("Response: {0}", responseData);
|
||||
} catch (Exception ex) {
|
||||
LOG.Error("Couldn't retrieve response: ", ex);
|
||||
|
@ -732,4 +898,417 @@ namespace GreenshotPlugin.Core {
|
|||
return responseData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 2.0 verification code receiver that runs a local server on a free port
|
||||
/// and waits for a call with the authorization verification code.
|
||||
/// </summary>
|
||||
public class LocalServerCodeReceiver {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(LocalServerCodeReceiver));
|
||||
private readonly ManualResetEvent _ready = new ManualResetEvent(true);
|
||||
|
||||
private string _loopbackCallback = "http://localhost:{0}/authorize/";
|
||||
/// <summary>
|
||||
/// The call back format. Expects one port parameter.
|
||||
/// Default: http://localhost:{0}/authorize/
|
||||
/// </summary>
|
||||
public string LoopbackCallbackUrl {
|
||||
get {
|
||||
return _loopbackCallback;
|
||||
}
|
||||
set {
|
||||
_loopbackCallback = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _closePageResponse =
|
||||
@"<html>
|
||||
<head><title>OAuth 2.0 Authentication CloudServiceName</title></head>
|
||||
<body>
|
||||
Greenshot received information from CloudServiceName. You can close this browser / tab if it is not closed itself...
|
||||
<script type='text/javascript'>
|
||||
window.setTimeout(function() {
|
||||
window.open('', '_self', '');
|
||||
window.close();
|
||||
}, 1000);
|
||||
if (window.opener) {
|
||||
window.opener.checkToken();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>";
|
||||
|
||||
/// <summary>
|
||||
/// HTML code to to return the _browser, default it will try to close the _browser / tab, this won't always work.
|
||||
/// You can use CloudServiceName where you want to show the CloudServiceName from your OAuth2 settings
|
||||
/// </summary>
|
||||
public string ClosePageResponse {
|
||||
get {
|
||||
return _closePageResponse;
|
||||
}
|
||||
set {
|
||||
_closePageResponse = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _redirectUri;
|
||||
/// <summary>
|
||||
/// The URL to redirect to
|
||||
/// </summary>
|
||||
protected string RedirectUri {
|
||||
get {
|
||||
if (!string.IsNullOrEmpty(_redirectUri)) {
|
||||
return _redirectUri;
|
||||
}
|
||||
|
||||
return _redirectUri = string.Format(_loopbackCallback, GetRandomUnusedPort());
|
||||
}
|
||||
}
|
||||
|
||||
private string _cloudServiceName;
|
||||
|
||||
private IDictionary<string, string> _returnValues = new Dictionary<string, string>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The OAuth code receiver
|
||||
/// </summary>
|
||||
/// <param name="authorizationUrl"></param>
|
||||
/// <returns>Dictionary with values</returns>
|
||||
public IDictionary<string, string> ReceiveCode(OAuth2Settings oauth2Settings) {
|
||||
// Set the redirect URL on the settings
|
||||
oauth2Settings.RedirectUrl = RedirectUri;
|
||||
_cloudServiceName = oauth2Settings.CloudServiceName;
|
||||
using (var listener = new HttpListener()) {
|
||||
listener.Prefixes.Add(oauth2Settings.RedirectUrl);
|
||||
try {
|
||||
listener.Start();
|
||||
|
||||
// Get the formatted FormattedAuthUrl
|
||||
string authorizationUrl = oauth2Settings.FormattedAuthUrl;
|
||||
LOG.DebugFormat("Open a browser with: {0}", authorizationUrl);
|
||||
Process.Start(authorizationUrl);
|
||||
|
||||
// Wait to get the authorization code response.
|
||||
var context = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
|
||||
_ready.Reset();
|
||||
|
||||
while (!context.AsyncWaitHandle.WaitOne(1000, true)) {
|
||||
LOG.Debug("Waiting for response");
|
||||
}
|
||||
} catch (Exception) {
|
||||
// Make sure we can clean up, also if the thead is aborted
|
||||
_ready.Set();
|
||||
throw;
|
||||
} finally {
|
||||
_ready.WaitOne();
|
||||
listener.Close();
|
||||
}
|
||||
}
|
||||
return _returnValues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a connection async, this allows us to break the waiting
|
||||
/// </summary>
|
||||
/// <param name="result">IAsyncResult</param>
|
||||
private void ListenerCallback(IAsyncResult result) {
|
||||
HttpListener listener = (HttpListener)result.AsyncState;
|
||||
|
||||
//If not listening return immediately as this method is called one last time after Close()
|
||||
if (!listener.IsListening) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use EndGetContext to complete the asynchronous operation.
|
||||
HttpListenerContext context = listener.EndGetContext(result);
|
||||
|
||||
|
||||
// Handle request
|
||||
HttpListenerRequest request = context.Request;
|
||||
try {
|
||||
NameValueCollection nameValueCollection = request.QueryString;
|
||||
|
||||
// Get response object.
|
||||
using (HttpListenerResponse response = context.Response) {
|
||||
// Write a "close" response.
|
||||
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(ClosePageResponse.Replace("CloudServiceName", _cloudServiceName));
|
||||
// Write to response stream.
|
||||
response.ContentLength64 = buffer.Length;
|
||||
using (var stream = response.OutputStream) {
|
||||
stream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new response URL with a dictionary that contains all the response query parameters.
|
||||
foreach (var name in nameValueCollection.AllKeys) {
|
||||
if (!_returnValues.ContainsKey(name)) {
|
||||
_returnValues.Add(name, nameValueCollection[name]);
|
||||
}
|
||||
}
|
||||
} catch (Exception) {
|
||||
context.Response.OutputStream.Close();
|
||||
throw;
|
||||
}
|
||||
_ready.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random, unused port.
|
||||
/// </summary>
|
||||
/// <returns>port to use</returns>
|
||||
private static int GetRandomUnusedPort() {
|
||||
var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
try {
|
||||
listener.Start();
|
||||
return ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
} finally {
|
||||
listener.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Code to simplify OAuth 2
|
||||
/// </summary>
|
||||
public static class OAuth2Helper {
|
||||
private const string REFRESH_TOKEN = "refresh_token";
|
||||
private const string ACCESS_TOKEN = "access_token";
|
||||
private const string CODE = "code";
|
||||
private const string CLIENT_ID = "client_id";
|
||||
private const string CLIENT_SECRET = "client_secret";
|
||||
private const string GRANT_TYPE = "grant_type";
|
||||
private const string AUTHORIZATION_CODE = "authorization_code";
|
||||
private const string REDIRECT_URI = "redirect_uri";
|
||||
private const string EXPIRES_IN = "expires_in";
|
||||
|
||||
/// <summary>
|
||||
/// Generate an OAuth 2 Token by using the supplied code
|
||||
/// </summary>
|
||||
/// <param name="code">Code to get the RefreshToken</param>
|
||||
/// <param name="settings">OAuth2Settings to update with the information that was retrieved</param>
|
||||
public static void GenerateRefreshToken(OAuth2Settings settings) {
|
||||
IDictionary<string, object> data = new Dictionary<string, object>();
|
||||
// Use the returned code to get a refresh code
|
||||
data.Add(CODE, settings.Code);
|
||||
data.Add(CLIENT_ID, settings.ClientId);
|
||||
data.Add(REDIRECT_URI, settings.RedirectUrl);
|
||||
data.Add(CLIENT_SECRET, settings.ClientSecret);
|
||||
data.Add(GRANT_TYPE, AUTHORIZATION_CODE);
|
||||
foreach (string key in settings.AdditionalAttributes.Keys) {
|
||||
data.Add(key, settings.AdditionalAttributes[key]);
|
||||
}
|
||||
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(settings.TokenUrl, HTTPMethod.POST);
|
||||
NetworkHelper.UploadFormUrlEncoded(webRequest, data);
|
||||
string accessTokenJsonResult = NetworkHelper.GetResponseAsString(webRequest, true);
|
||||
|
||||
IDictionary<string, object> refreshTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult);
|
||||
if (refreshTokenResult.ContainsKey("error")) {
|
||||
if (refreshTokenResult.ContainsKey("error_description")) {
|
||||
throw new Exception(string.Format("{0} - {1}", refreshTokenResult["error"], refreshTokenResult["error_description"]));
|
||||
} else {
|
||||
throw new Exception((string)refreshTokenResult["error"]);
|
||||
}
|
||||
}
|
||||
|
||||
// gives as described here: https://developers.google.com/identity/protocols/OAuth2InstalledApp
|
||||
// "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
|
||||
// "expires_in":3920,
|
||||
// "token_type":"Bearer",
|
||||
// "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
|
||||
settings.AccessToken = (string)refreshTokenResult[ACCESS_TOKEN] as string;
|
||||
settings.RefreshToken = (string)refreshTokenResult[REFRESH_TOKEN] as string;
|
||||
|
||||
object seconds = refreshTokenResult[EXPIRES_IN];
|
||||
if (seconds != null) {
|
||||
settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds);
|
||||
}
|
||||
settings.Code = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go out and retrieve a new access token via refresh-token with the TokenUrl in the settings
|
||||
/// Will upate the access token, refresh token, expire date
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
public static void GenerateAccessToken(OAuth2Settings settings) {
|
||||
IDictionary<string, object> data = new Dictionary<string, object>();
|
||||
data.Add(REFRESH_TOKEN, settings.RefreshToken);
|
||||
data.Add(CLIENT_ID, settings.ClientId);
|
||||
data.Add(CLIENT_SECRET, settings.ClientSecret);
|
||||
data.Add(GRANT_TYPE, REFRESH_TOKEN);
|
||||
foreach (string key in settings.AdditionalAttributes.Keys) {
|
||||
data.Add(key, settings.AdditionalAttributes[key]);
|
||||
}
|
||||
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(settings.TokenUrl, HTTPMethod.POST);
|
||||
NetworkHelper.UploadFormUrlEncoded(webRequest, data);
|
||||
string accessTokenJsonResult = NetworkHelper.GetResponseAsString(webRequest, true);
|
||||
|
||||
// gives as described here: https://developers.google.com/identity/protocols/OAuth2InstalledApp
|
||||
// "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
|
||||
// "expires_in":3920,
|
||||
// "token_type":"Bearer",
|
||||
|
||||
IDictionary<string, object> accessTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult);
|
||||
if (accessTokenResult.ContainsKey("error")) {
|
||||
if ("invalid_grant" == (string)accessTokenResult["error"]) {
|
||||
// Refresh token has also expired, we need a new one!
|
||||
settings.RefreshToken = null;
|
||||
settings.AccessToken = null;
|
||||
settings.AccessTokenExpires = DateTimeOffset.MinValue;
|
||||
settings.Code = null;
|
||||
return;
|
||||
} else {
|
||||
if (accessTokenResult.ContainsKey("error_description")) {
|
||||
throw new Exception(string.Format("{0} - {1}", accessTokenResult["error"], accessTokenResult["error_description"]));
|
||||
} else {
|
||||
throw new Exception((string)accessTokenResult["error"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings.AccessToken = (string)accessTokenResult[ACCESS_TOKEN] as string;
|
||||
if (accessTokenResult.ContainsKey(REFRESH_TOKEN)) {
|
||||
// Refresh the refresh token :)
|
||||
settings.RefreshToken = (string)accessTokenResult[REFRESH_TOKEN] as string;
|
||||
}
|
||||
object seconds = accessTokenResult[EXPIRES_IN];
|
||||
if (seconds != null) {
|
||||
settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds);
|
||||
} else {
|
||||
settings.AccessTokenExpires = DateTimeOffset.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate by using the mode specified in the settings
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings</param>
|
||||
/// <returns>false if it was canceled, true if it worked, exception if not</returns>
|
||||
public static bool Authenticate(OAuth2Settings settings) {
|
||||
bool completed = true;
|
||||
switch (settings.AuthorizeMode) {
|
||||
case OAuth2AuthorizeMode.LocalServer:
|
||||
completed = AuthenticateViaLocalServer(settings);
|
||||
break;
|
||||
case OAuth2AuthorizeMode.EmbeddedBrowser:
|
||||
completed = AuthenticateViaEmbeddedBrowser(settings);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException(string.Format("Authorize mode '{0}' is not 'yet' implemented.", settings.AuthorizeMode));
|
||||
}
|
||||
return completed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate via an embedded browser
|
||||
/// If this works, return the code
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings with the Auth / Token url etc</param>
|
||||
/// <returns>true if completed, false if canceled</returns>
|
||||
private static bool AuthenticateViaEmbeddedBrowser(OAuth2Settings settings) {
|
||||
if (string.IsNullOrEmpty(settings.CloudServiceName)) {
|
||||
throw new ArgumentNullException("CloudServiceName");
|
||||
}
|
||||
if (settings.BrowserSize == Size.Empty) {
|
||||
throw new ArgumentNullException("BrowserSize");
|
||||
}
|
||||
OAuthLoginForm loginForm = new OAuthLoginForm(string.Format("Authorize {0}", settings.CloudServiceName), settings.BrowserSize, settings.FormattedAuthUrl, settings.RedirectUrl);
|
||||
loginForm.ShowDialog();
|
||||
if (loginForm.IsOk) {
|
||||
string code;
|
||||
if (loginForm.CallbackParameters.TryGetValue(CODE, out code) && !string.IsNullOrEmpty(code)) {
|
||||
settings.Code = code;
|
||||
GenerateRefreshToken(settings);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate via a local server by using the LocalServerCodeReceiver
|
||||
/// If this works, return the code
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings with the Auth / Token url etc</param>
|
||||
/// <returns>true if completed</returns>
|
||||
private static bool AuthenticateViaLocalServer(OAuth2Settings settings) {
|
||||
var codeReceiver = new LocalServerCodeReceiver();
|
||||
IDictionary<string, string> result = codeReceiver.ReceiveCode(settings);
|
||||
|
||||
string code;
|
||||
if (result.TryGetValue(CODE, out code) && !string.IsNullOrEmpty(code)) {
|
||||
settings.Code = code;
|
||||
GenerateRefreshToken(settings);
|
||||
return true;
|
||||
}
|
||||
string error;
|
||||
if (result.TryGetValue("error", out error)) {
|
||||
string errorDescription;
|
||||
if (result.TryGetValue("error_description", out errorDescription)) {
|
||||
throw new Exception(errorDescription);
|
||||
}
|
||||
if ("access_denied" == error) {
|
||||
throw new UnauthorizedAccessException("Access denied");
|
||||
} else {
|
||||
throw new Exception(error);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple helper to add the Authorization Bearer header
|
||||
/// </summary>
|
||||
/// <param name="webRequest">WebRequest</param>
|
||||
/// <param name="settings">OAuth2Settings</param>
|
||||
public static void AddOAuth2Credentials(HttpWebRequest webRequest, OAuth2Settings settings) {
|
||||
if (!string.IsNullOrEmpty(settings.AccessToken)) {
|
||||
webRequest.Headers.Add("Authorization", "Bearer " + settings.AccessToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check and authenticate or refresh tokens
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings</param>
|
||||
public static void CheckAndAuthenticateOrRefresh(OAuth2Settings settings) {
|
||||
// Get Refresh / Access token
|
||||
if (string.IsNullOrEmpty(settings.RefreshToken)) {
|
||||
if (!Authenticate(settings)) {
|
||||
throw new Exception("Authentication cancelled");
|
||||
}
|
||||
}
|
||||
if (settings.IsAccessTokenExpired) {
|
||||
GenerateAccessToken(settings);
|
||||
// Get Refresh / Access token
|
||||
if (string.IsNullOrEmpty(settings.RefreshToken)) {
|
||||
if (!Authenticate(settings)) {
|
||||
throw new Exception("Authentication cancelled");
|
||||
}
|
||||
GenerateAccessToken(settings);
|
||||
}
|
||||
}
|
||||
if (settings.IsAccessTokenExpired) {
|
||||
throw new Exception("Authentication failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CreateWebRequest ready for OAuth 2 access
|
||||
/// </summary>
|
||||
/// <param name="method">HTTPMethod</param>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="settings">OAuth2Settings</param>
|
||||
/// <returns>HttpWebRequest</returns>
|
||||
public static HttpWebRequest CreateOAuth2WebRequest(HTTPMethod method, string url, OAuth2Settings settings) {
|
||||
CheckAndAuthenticateOrRefresh(settings);
|
||||
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, method);
|
||||
AddOAuth2Credentials(webRequest, settings);
|
||||
return webRequest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
@ -28,39 +29,39 @@ using log4net;
|
|||
|
||||
namespace GreenshotPlugin.Core {
|
||||
public class SourceforgeFile {
|
||||
private string file;
|
||||
private readonly string _file;
|
||||
public string File {
|
||||
get {return file;}
|
||||
get {return _file;}
|
||||
}
|
||||
private DateTime pubdate;
|
||||
private readonly DateTime _pubdate;
|
||||
public DateTime Pubdate {
|
||||
get {return pubdate;}
|
||||
get {return _pubdate;}
|
||||
}
|
||||
private string link;
|
||||
private readonly string _link;
|
||||
public string Link {
|
||||
get {return link;}
|
||||
get {return _link;}
|
||||
}
|
||||
private string directLink;
|
||||
private readonly string _directLink;
|
||||
public string DirectLink {
|
||||
get {return directLink;}
|
||||
get {return _directLink;}
|
||||
}
|
||||
private Version version;
|
||||
private Version _version;
|
||||
public Version Version {
|
||||
get {return version;}
|
||||
get {return _version;}
|
||||
set {
|
||||
version = value;
|
||||
_version = value;
|
||||
}
|
||||
}
|
||||
private string language;
|
||||
private string _language;
|
||||
public string Language {
|
||||
get {return language;}
|
||||
set {language = value;}
|
||||
get {return _language;}
|
||||
set {_language = value;}
|
||||
}
|
||||
|
||||
public bool isExe {
|
||||
get {
|
||||
if (file != null) {
|
||||
return file.ToLower().EndsWith(".exe");
|
||||
if (_file != null) {
|
||||
return _file.ToLower().EndsWith(".exe");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -68,8 +69,8 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
public bool isUnstable {
|
||||
get {
|
||||
if (file != null) {
|
||||
return file.ToLower().Contains("unstable");
|
||||
if (_file != null) {
|
||||
return _file.ToLower().Contains("unstable");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -77,18 +78,18 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
public bool isReleaseCandidate {
|
||||
get {
|
||||
if (file != null) {
|
||||
return Regex.IsMatch(file.ToLower(), "rc[0-9]+");
|
||||
if (_file != null) {
|
||||
return Regex.IsMatch(_file.ToLower(), "rc[0-9]+");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SourceforgeFile(string file, string pubdate, string link, string directLink) {
|
||||
this.file = file;
|
||||
this.pubdate = DateTime.Parse(pubdate);
|
||||
this.link = link;
|
||||
this.directLink = directLink;
|
||||
this._file = file;
|
||||
DateTime.TryParse(pubdate, out _pubdate);
|
||||
this._link = link;
|
||||
this._directLink = directLink;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
|
@ -113,10 +114,9 @@ namespace GreenshotPlugin.Core {
|
|||
/// </summary>
|
||||
/// <returns>Dictionary<string, Dictionary<string, RssFile>> with files and their RssFile "description"</returns>
|
||||
public static Dictionary<string, Dictionary<string, SourceforgeFile>> readRSS() {
|
||||
HttpWebRequest webRequest;
|
||||
XmlDocument rssDoc = new XmlDocument();
|
||||
try {
|
||||
webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(RSSFEED);
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(RSSFEED);
|
||||
XmlTextReader rssReader = new XmlTextReader(webRequest.GetResponse().GetResponseStream());
|
||||
|
||||
// Load the XML content into a XmlDocument
|
||||
|
|
|
@ -1,90 +1,166 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
public static class EncryptionHelper {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(EncryptionHelper));
|
||||
private const string RGBIV = "dlgjowejgogkklwj";
|
||||
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
|
||||
|
||||
/// <summary>
|
||||
/// A simply rijndael aes encryption, can be used to store passwords
|
||||
/// </summary>
|
||||
/// <param name="ClearText">the string to call upon</param>
|
||||
/// <returns>an encryped string in base64 form</returns>
|
||||
public static string Encrypt(this string ClearText) {
|
||||
string returnValue = ClearText;
|
||||
try {
|
||||
byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText);
|
||||
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
||||
|
||||
using (MemoryStream ms = new MemoryStream()) {
|
||||
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
||||
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write)) {
|
||||
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
|
||||
cs.FlushFinalBlock();
|
||||
|
||||
returnValue = Convert.ToBase64String(ms.ToArray());
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.ErrorFormat("Error encrypting, error: ", ex.Message);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simply rijndael aes decryption, can be used to store passwords
|
||||
/// </summary>
|
||||
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
|
||||
/// <returns>Decrypeted text</returns>
|
||||
public static string Decrypt(this string EncryptedText) {
|
||||
string returnValue = EncryptedText;
|
||||
try {
|
||||
byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);
|
||||
using (MemoryStream ms = new MemoryStream()) {
|
||||
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
||||
|
||||
|
||||
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
||||
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
||||
|
||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write)) {
|
||||
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
|
||||
cs.FlushFinalBlock();
|
||||
returnValue = Encoding.ASCII.GetString(ms.ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
public static class StringExtensions {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(StringExtensions));
|
||||
private const string RGBIV = "dlgjowejgogkklwj";
|
||||
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
|
||||
|
||||
/// <summary>
|
||||
/// Format a string with the specified object
|
||||
/// </summary>
|
||||
/// <param name="format">String with formatting, like {name}</param>
|
||||
/// <param name="source">Object used for the formatting</param>
|
||||
/// <returns>Formatted string</returns>
|
||||
public static string FormatWith(this string format, object source) {
|
||||
return FormatWith(format, null, source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the string "format" with the source
|
||||
/// </summary>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="provider"></param>
|
||||
/// <param name="source">object with properties, if a property has the type IDictionary string,string it can used these parameters too</param>
|
||||
/// <returns>Formatted string</returns>
|
||||
public static string FormatWith(this string format, IFormatProvider provider, object source) {
|
||||
if (format == null) {
|
||||
throw new ArgumentNullException("format");
|
||||
}
|
||||
|
||||
IDictionary<string, object> properties = new Dictionary<string, object>();
|
||||
foreach(var propertyInfo in source.GetType().GetProperties()) {
|
||||
if (propertyInfo.CanRead && propertyInfo.CanWrite) {
|
||||
object value = propertyInfo.GetValue(source, null);
|
||||
if (propertyInfo.PropertyType != typeof(IDictionary<string, string>)) {
|
||||
properties.Add(propertyInfo.Name, value);
|
||||
} else {
|
||||
IDictionary<string, string> dictionary = (IDictionary<string, string>)value;
|
||||
foreach (var propertyKey in dictionary.Keys) {
|
||||
properties.Add(propertyKey, dictionary[propertyKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
|
||||
List<object> values = new List<object>();
|
||||
string rewrittenFormat = r.Replace(format, delegate(Match m) {
|
||||
Group startGroup = m.Groups["start"];
|
||||
Group propertyGroup = m.Groups["property"];
|
||||
Group formatGroup = m.Groups["format"];
|
||||
Group endGroup = m.Groups["end"];
|
||||
|
||||
object value;
|
||||
if (properties.TryGetValue(propertyGroup.Value, out value)) {
|
||||
values.Add(value);
|
||||
} else {
|
||||
values.Add(source);
|
||||
}
|
||||
return new string('{', startGroup.Captures.Count) + (values.Count - 1) + formatGroup.Value + new string('}', endGroup.Captures.Count);
|
||||
});
|
||||
|
||||
return string.Format(provider, rewrittenFormat, values.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simply rijndael aes encryption, can be used to store passwords
|
||||
/// </summary>
|
||||
/// <param name="ClearText">the string to call upon</param>
|
||||
/// <returns>an encryped string in base64 form</returns>
|
||||
public static string Encrypt(this string ClearText) {
|
||||
string returnValue = ClearText;
|
||||
try {
|
||||
byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText);
|
||||
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
||||
|
||||
using (MemoryStream ms = new MemoryStream()) {
|
||||
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
||||
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write)) {
|
||||
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
|
||||
cs.FlushFinalBlock();
|
||||
|
||||
returnValue = Convert.ToBase64String(ms.ToArray());
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.ErrorFormat("Error encrypting, error: ", ex.Message);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simply rijndael aes decryption, can be used to store passwords
|
||||
/// </summary>
|
||||
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
|
||||
/// <returns>Decrypeted text</returns>
|
||||
public static string Decrypt(this string EncryptedText) {
|
||||
string returnValue = EncryptedText;
|
||||
try {
|
||||
byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);
|
||||
using (MemoryStream ms = new MemoryStream()) {
|
||||
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
||||
|
||||
|
||||
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
||||
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
||||
|
||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write)) {
|
||||
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
|
||||
cs.FlushFinalBlock();
|
||||
returnValue = Encoding.ASCII.GetString(ms.ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read "streamextensions" :)
|
||||
/// </summary>
|
||||
/// <param name="input">Stream</param>
|
||||
/// <param name="output">Stream</param>
|
||||
public static void CopyTo(this Stream input, Stream output) {
|
||||
byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size
|
||||
int bytesRead;
|
||||
|
||||
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) {
|
||||
output.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
65
GreenshotPlugin/Core/WmInputLangChangeRequestFilter.cs
Normal file
65
GreenshotPlugin/Core/WmInputLangChangeRequestFilter.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This IMessageFilter filters out all WM_INPUTLANGCHANGEREQUEST messages which go to a handle which is >32 bits.
|
||||
/// The need for this is documented here: http://stackoverflow.com/a/32021586
|
||||
/// </summary>
|
||||
public class WmInputLangChangeRequestFilter : IMessageFilter
|
||||
{
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(WmInputLangChangeRequestFilter));
|
||||
|
||||
/// <summary>
|
||||
/// This will do some filtering
|
||||
/// </summary>
|
||||
/// <param name="m">Message</param>
|
||||
/// <returns>true if the message should be filtered</returns>
|
||||
public bool PreFilterMessage(ref Message m)
|
||||
{
|
||||
return PreFilterMessageExternal(ref m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Also used in the MainForm WndProc
|
||||
/// </summary>
|
||||
/// <param name="m">Message</param>
|
||||
/// <returns>true if the message should be filtered</returns>
|
||||
public static bool PreFilterMessageExternal(ref Message m)
|
||||
{
|
||||
WindowsMessages message = (WindowsMessages)m.Msg;
|
||||
if (message == WindowsMessages.WM_INPUTLANGCHANGEREQUEST || message == WindowsMessages.WM_INPUTLANGCHANGE)
|
||||
{
|
||||
LOG.WarnFormat("Filtering: {0}, {1:X} - {2:X} - {3:X}", message, m.LParam.ToInt64(), m.WParam.ToInt64(), m.HWnd.ToInt64());
|
||||
// For now we always return true
|
||||
return true;
|
||||
// But it could look something like this:
|
||||
//return (m.LParam.ToInt64() | 0x7FFFFFFF) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
<Compile Include="Core\CaptureHandler.cs" />
|
||||
<Compile Include="Core\EventDelay.cs" />
|
||||
<Compile Include="Core\FastBitmap.cs" />
|
||||
<Compile Include="Core\WmInputLangChangeRequestFilter.cs" />
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="IEInterop\IHTMLBodyElement.cs" />
|
||||
<Compile Include="IEInterop\IHTMLCurrentStyle.cs" />
|
||||
|
@ -155,7 +156,7 @@
|
|||
<Compile Include="Core\CoreConfiguration.cs" />
|
||||
<Compile Include="Core\CredentialsHelper.cs" />
|
||||
<Compile Include="Core\Effects.cs" />
|
||||
<Compile Include="Core\EncryptionHelper.cs" />
|
||||
<Compile Include="Core\StringExtensions.cs" />
|
||||
<Compile Include="Core\FilenameHelper.cs" />
|
||||
<Compile Include="Core\ImageOutput.cs" />
|
||||
<Compile Include="Core\InterfaceUtils.cs" />
|
||||
|
|
|
@ -58,7 +58,10 @@ namespace Greenshot.IniFile {
|
|||
/// <summary>
|
||||
/// Flag to specify if values have been changed
|
||||
/// </summary>
|
||||
public bool IsDirty = false;
|
||||
public bool IsDirty {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supply values we can't put as defaults
|
||||
|
|
80
appveyor.yml
80
appveyor.yml
|
@ -1,9 +1,11 @@
|
|||
version: 1.3.0.{build}
|
||||
version: 1.2.7.{build}
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 1.2
|
||||
skip_tags: true
|
||||
configuration: Release
|
||||
platform: Any CPU
|
||||
clone_depth: 1
|
||||
assembly_info:
|
||||
patch: true
|
||||
file: '**\AssemblyInfo.*'
|
||||
|
@ -11,32 +13,40 @@ assembly_info:
|
|||
assembly_file_version: '{version}'
|
||||
assembly_informational_version: '{version}-$(build_type)-$(APPVEYOR_REPO_COMMIT)'
|
||||
environment:
|
||||
credentials_box_client_id: key
|
||||
credentials_box_client_secret: secret
|
||||
credentials_dropbox_consumer_key: key
|
||||
credentials_dropbox_consumer_secret: secret
|
||||
credentials_flickr_consumer_key: key
|
||||
credentials_flickr_consumer_secret: secret
|
||||
credentials_imgur_consumer_key: key
|
||||
credentials_imgur_consumer_secret: secret
|
||||
credentials_photobucket_consumer_key: key
|
||||
credentials_photobucket_consumer_secret: secret
|
||||
credentials_picasa_consumer_key: key
|
||||
credentials_picasa_consumer_secret: secret
|
||||
sourceforge_host: frs.sourceforge.net
|
||||
sourceforge_user: user
|
||||
sourceforge_password: password
|
||||
sourceforge_hostkey: ssh-rsa 2048 b0:a8:eb:30:ce:1a:0e:6a:4d:7a:6b:3a:0a:c6:27:60
|
||||
sourceforge_targetpath: /home/frs/project/greenshot/Greenshot/Greenshot 1.3/
|
||||
build_type: UNSTABLE
|
||||
rsakey: key
|
||||
credentials_box_client_id:
|
||||
secure: 8MKxTOowo2fat6cNXGbFfvn6typiEtmCKsrptrWiEFUEoKlT1DUn40iGNcIELRA1
|
||||
credentials_box_client_secret:
|
||||
secure: hJhzDVJuGd/WMnoSXhosvOM/1PGcYlKbtQjA6xyrmnmZcqCTMzqIdA6JXlo/V2Br
|
||||
credentials_dropbox_consumer_key:
|
||||
secure: Da/6KY1cu9CUM3iOqSpcUw==
|
||||
credentials_dropbox_consumer_secret:
|
||||
secure: KkyKyUY+buT/MZagXDP4cw==
|
||||
credentials_flickr_consumer_key:
|
||||
secure: fY8s0OkOMYwCjSZoL/6yZcP8xeT6J2EJLjbUMI5lAW42S5QT2U2B41KrmeP2NpnQ
|
||||
credentials_flickr_consumer_secret:
|
||||
secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw=
|
||||
credentials_imgur_consumer_key:
|
||||
secure: z8S4QZ3/InPe3dgCf0CNyS0VGKuRyjjP8WMAq+AkK5OZJxZcbIxwobjgelE5CWYL
|
||||
credentials_imgur_consumer_secret:
|
||||
secure: ovfXJRorkkKUzbMXuZ4m0U6KF4icngmS+nzSljXJGSKfhI+GNXbMNa//mKYfTCXI
|
||||
credentials_photobucket_consumer_key:
|
||||
secure: oo9GD1Y8dkrli6hMfnnYsw==
|
||||
credentials_photobucket_consumer_secret:
|
||||
secure: GiNPoe9klM/YkoHIA/YHqOYrIaYwSFK7Ph9m8jT9uPP1l6+Hd5K8dVMw5DNa50oG
|
||||
credentials_picasa_consumer_key:
|
||||
secure: bjKXhFZkDqaq98XBrz5oQKQfT8CLpuv2ZAiBIwkzloaAPUs97b5yx6h/xFaE4NLS
|
||||
credentials_picasa_consumer_secret:
|
||||
secure: yNptTpmJWypbu9alOQtetxU66drr2FKxoPflNgRJdag=
|
||||
build_type: RELEASE
|
||||
rsakey:
|
||||
secure: GNomwdlwZOCyd8d7xEWTnMVs1lpOeHvF+tlnvcbXGovLRtwAp2Ufu0r7paGY7BHGGkIs2WE7xUfyQ9UauVB+58JZ6fwVega8ucUgVJhl4x0QQNN2d6sULUhHfhuEHmxw+FDO/FxKFE6Lmf+ZRY+OGiw0wKIl4qD7mGRHcDQTipNEsTbau8HzqRVCdu3dx7pODC61DlsbO71xLF7UlqnmuZE+91Zz3V6AgaqE246n1499d6bXBYw1AH+8opNnKDFLnTHf7hUVcZn9mj6tKZXeTCuVUOr/SVQcgHKxlBlqzhfaEkxCR5GPtzQRqwDMxEycmFvj2wNP/sie6UEGhQxE4YMCc2OgqNOkpc5BbP/fxLr/SLFOEf1XXzTWCFMhsgpHx7TZbgQH26sa0rK/xaBRacZlwAaNk7V2nFZT7TebYEFy6zWNr9Y+IyeXIofj42XQTNXv8d8hyh+UYLByVEFYRf2DnActQkZQyNdWjZ+CxDV50QSZZs8FT3IIqraHYKsj2ITAN5LrUtWCi7bpNJL0UGo0EJiB2i0bp++tEAAwyrCljxI8d4bbGl/flHk/xd+ysQPnomndijeObjguEzqT8pyXZluSZhF+lI50mIDhMdtdAfMi5yn5RW7P6NWOSlC8xgQQgMZylsuSvRflKbEd/gsoDyEOnakNcdH2jekt9OD6GnuYM7iHkbMC89LBZ0VaHNGvCC+BQXdGUG7O9R3NthZcDXE7q7xbtGRB5ncVQDRfKoT5HVfiV6bSDrcfRODiuR59mZgiSYtZG+3kQWYUKn2wagvZKckGukA0SlOuTRCKZhgLcVHhWeRWeGE3iJ8K6BeHf2EgB8Qr6ayTyTUjBcn+u4qqWKgkvG4qRavlvrBSdMrAXWIKE8vSq1od0A2ZzP6+HCsrkuUR+HFfpE2dpjeckoa5vATQgyn8j5x11iIOB9HnT3YKbZ0aTU4rQgYMJXA/fPcgKDGkAPdgtGbQLssy/mwSdsXBYtMgEcs7vI9laR8Ik+NK2dbFHGFPnxS43WToGyKBxojt8SZbgPJXm22WRrN1+9AZvvhI7/mpZiEE7HWgNRClZYuqbfCMpelLGvVq832OLjelrWMJ0XBVNHnOw0p8qZKI1UpqQJXX1nL8j3JttEVHsfryIanM03kNDL0dX1VAKECKUMCVQ6i6tG4VWsR0C2JccPJ3PSoPgo5KMJhuZNaBoiPjZ2eaMREV6vUYbBYzrvdDQzUcE2stacREl4eJzGJ4GP5h08GQmIirGF/SCyZV1CadAbKZVjqb70XpIbE6NT/+84O82LZR4ui5KgTAv87lTZgvNJ7LxM7rRg1awj/iBxQeARNJxuPMPlk1CVx8Z3091UdL1K1avPKa85lCRwCkDKLcJPO9tlqi4dVjCrwpoCJkQMm3fbTl/BgHn00/RsnFZ2qfl5m2DyF+XuaOPauzsRdLUFAC4h44qoUuzRb4Pv6RFhN5CI4fddRKafNBHU9f69UCkO080/hIjTdj0+bpr4oNY4UEi80huyJY/c0iUPE8o48qBB8F3cW30SwhPmuphn4/18lB8GEwEPqoatmli4QRaDFUCUf9Hj0DEUqEAya/OHOW7/PvWcw/l/ZaIMUpOZ6q0xvPDAXokFRJAWzZhG7hNbWNEzQ3f/BjlYlYsBtMY0JUU8mH6YxwIzIGbHiLTBC0OglH0rDd5W+3NaUG9FZ//o9MAP5j2QqwSuFWXppbigh4zk+h17eJn5zhld7dtvOr+YmgYULj6NFIDKBZHUJdqLYScVzdc1p812FCCBcLmmw4RnwuF+RldHixTdy4UZ17T/hD4OLpWCINl9lUAficC0OFeLJLHxFW6Em8SCbZ3aUtFDIQD8oTqzUHZhGWYF2ukrOc8Dzm4FQ8xy3BhqfntTod1gwoilIirsP/z+GGMnTltkqiqK+gCmkVOfICwNFmHltZeJrmDQ4YU5abR09Yr1TaAk3CzWjV1XGBaf/oek0+tFkMOtZNdFRdlzLLE90PsZZFFnZhFBoNoOhYnMB9K2VqgEpJs0nXvF6qBOllptcpBYUYMzMdb0Ggu6m1d/phxuBuOsm+Xtr0Zw8Xd0vxIOQNDGsskCDIEUYWYajw2i66MmRPRyFEennXfLA0WIPpztXvfsrKjf42rjE3RukBsRff1Sci68cel4fGfmvj2y7gW0Tt
|
||||
before_build:
|
||||
- ps: iex (new-object Net.WebClient).DownloadString("https://bitbucket.org/greenshot/greenshot/raw/master/prebuild.ps1")
|
||||
- ps: iex (new-object Net.WebClient).DownloadString("https://bitbucket.org/greenshot/greenshot/raw/1.2/prebuild.ps1")
|
||||
build:
|
||||
project: greenshot\greenshot.sln
|
||||
verbosity: normal
|
||||
after_build:
|
||||
- ps: iex (new-object Net.WebClient).DownloadString("https://bitbucket.org/greenshot/greenshot/raw/master/build.ps1")
|
||||
- ps: iex (new-object Net.WebClient).DownloadString("https://bitbucket.org/greenshot/greenshot/raw/1.2/build.ps1")
|
||||
test: off
|
||||
artifacts:
|
||||
- path: Greenshot\releases\Greenshot*INSTALLER*.exe
|
||||
|
@ -49,12 +59,26 @@ artifacts:
|
|||
name: Readme
|
||||
- path: Greenshot\releases\Greenshot-DEBUGSYMBOLS*.zip
|
||||
name: DEBUGSYMBOLS
|
||||
deploy_script:
|
||||
- ps: iex (new-object Net.WebClient).DownloadString("https://bitbucket.org/greenshot/greenshot/raw/master/deploy.ps1")
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
|
||||
description:
|
||||
auth_token:
|
||||
secure: 4sYcNGg7byBFtR7EkJHS8d3H3qP0u0LodlJWCV7g/4jEyv3vvVxqzh19zZ6Zgrf1
|
||||
prerelease: true
|
||||
on:
|
||||
build_type: UNSTABLE
|
||||
- provider: GitHub
|
||||
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
|
||||
auth_token:
|
||||
secure: 4sYcNGg7byBFtR7EkJHS8d3H3qP0u0LodlJWCV7g/4jEyv3vvVxqzh19zZ6Zgrf1
|
||||
on:
|
||||
build_type: RELEASE
|
||||
notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- robin@getgreenshot.org
|
||||
on_build_success: false
|
||||
on_build_failure: false
|
||||
on_build_status_changed: true
|
||||
- jens@getgreenshot.org
|
||||
on_build_success: true
|
||||
on_build_failure: true
|
||||
on_build_status_changed: false
|
80
deploy.ps1
80
deploy.ps1
|
@ -1,80 +0,0 @@
|
|||
################################################################
|
||||
# Greenshot DEPLOY script, written for the Windows Power Shell
|
||||
# Assumes the installation of Microsoft .NET Framework 4.5
|
||||
################################################################
|
||||
# Greenshot - a free and open source screenshot tool
|
||||
# Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
|
||||
#
|
||||
# For more information see: http://getgreenshot.org/
|
||||
# The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
################################################################
|
||||
|
||||
# This script needs some environment variables to work:
|
||||
# $env:sourceforge_host with the hostname
|
||||
# $env:sourceforge_user with the username
|
||||
# $env:sourceforge_password with the password for the username
|
||||
# $env:sourceforge_hostkey with the hosts key (ssh-rsa 2048 xx:xx:xx:xx:...)
|
||||
# $env:sourceforge_targetpath with the target location
|
||||
|
||||
try {
|
||||
# Load WinSCP .NET assembly
|
||||
Add-Type -Path "Greenshot\tools\WinSCP\WinSCPnet.dll"
|
||||
|
||||
# Setup session options
|
||||
$sessionOptions = New-Object WinSCP.SessionOptions
|
||||
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
|
||||
$sessionOptions.HostName = $env:sourceforge_host
|
||||
$sessionOptions.UserName = $env:sourceforge_user
|
||||
$sessionOptions.Password = $env:sourceforge_password
|
||||
$sessionOptions.SshHostKeyFingerprint = $env:sourceforge_hostkey
|
||||
|
||||
$session = New-Object WinSCP.Session
|
||||
|
||||
try {
|
||||
# Connect
|
||||
$session.Open($sessionOptions)
|
||||
|
||||
# Upload files
|
||||
$transferOptions = New-Object WinSCP.TransferOptions
|
||||
$transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
|
||||
|
||||
$artifactbase = "$(get-location)\Greenshot\releases"
|
||||
# The list of all the artifacts that need to be uploaded
|
||||
@(
|
||||
"$artifactbase\Greenshot-INSTALLER*.exe",
|
||||
"$artifactbase\Greenshot-NO-INSTALLER*.zip",
|
||||
"$artifactbase\Greenshot_for_PortableApps*.exe",
|
||||
"$artifactbase\additional_files\readme.txt"
|
||||
) | foreach {
|
||||
$transferResult = $session.PutFiles($_ , $env:sourceforge_targetpath, $False, $transferOptions)
|
||||
|
||||
# Throw on any error
|
||||
$transferResult.Check()
|
||||
|
||||
# Print results
|
||||
foreach ($transfer in $transferResult.Transfers) {
|
||||
Write-Host ("Upload of {0} to {1} succeeded" -f $transfer.FileName, $env:sourceforge_host)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
# Disconnect, clean up
|
||||
$session.Dispose()
|
||||
}
|
||||
|
||||
} catch [Exception] {
|
||||
Write-Host "Error: "$_.Exception
|
||||
exit 1
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue