mirror of
https://github.com/greenshot/greenshot
synced 2025-08-19 13:10:00 -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) {
|
if (e.Index > -1) {
|
||||||
FontFamily fontFamily = Items[e.Index] as FontFamily;
|
FontFamily fontFamily = Items[e.Index] as FontFamily;
|
||||||
FontStyle fs = FontStyle.Regular;
|
FontStyle fontStyle = FontStyle.Regular;
|
||||||
if (!fontFamily.IsStyleAvailable(FontStyle.Regular)) {
|
if (!fontFamily.IsStyleAvailable(FontStyle.Regular)) {
|
||||||
if (fontFamily.IsStyleAvailable(FontStyle.Bold)) {
|
if (fontFamily.IsStyleAvailable(FontStyle.Bold)) {
|
||||||
fs = FontStyle.Bold;
|
fontStyle = FontStyle.Bold;
|
||||||
} else if (fontFamily.IsStyleAvailable(FontStyle.Italic)) {
|
} else if (fontFamily.IsStyleAvailable(FontStyle.Italic)) {
|
||||||
fs = FontStyle.Italic;
|
fontStyle = FontStyle.Italic;
|
||||||
} else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout)) {
|
} else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout)) {
|
||||||
fs = FontStyle.Strikeout;
|
fontStyle = FontStyle.Strikeout;
|
||||||
} else if (fontFamily.IsStyleAvailable(FontStyle.Underline)) {
|
} 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)) {
|
try {
|
||||||
// Make sure the text is visible by centering it in the line
|
DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name);
|
||||||
using(StringFormat stringFormat = new StringFormat()) {
|
} catch {
|
||||||
stringFormat.LineAlignment = StringAlignment.Center;
|
// If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular'
|
||||||
e.Graphics.DrawString(fontFamily.Name, font, Brushes.Black, e.Bounds, stringFormat);
|
DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Uncomment this if you actually like the way the focus rectangle looks
|
// Uncomment this if you actually like the way the focus rectangle looks
|
||||||
//e.DrawFocusRectangle ();
|
//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) {
|
void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
||||||
if (PropertyChanged != null) {
|
if (PropertyChanged != null) {
|
||||||
PropertyChanged(this, new PropertyChangedEventArgs("Text"));
|
PropertyChanged(this, new PropertyChangedEventArgs("Text"));
|
||||||
|
|
|
@ -135,7 +135,7 @@ namespace Greenshot.Destinations {
|
||||||
string filepath = FilenameHelper.FillVariables(conf.OutputFilePath, false);
|
string filepath = FilenameHelper.FillVariables(conf.OutputFilePath, false);
|
||||||
try {
|
try {
|
||||||
fullPath = Path.Combine(filepath, filename);
|
fullPath = Path.Combine(filepath, filename);
|
||||||
} catch (ArgumentException ae) {
|
} catch (ArgumentException) {
|
||||||
// configured filename or path not valid, show error message...
|
// configured filename or path not valid, show error message...
|
||||||
LOG.InfoFormat("Generated path or filename not valid: {0}, {1}", filepath, filename);
|
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
|
// Only use double-buffering when we are NOT in a Terminal Server session
|
||||||
DoubleBuffered = !isTerminalServerSession;
|
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)
|
// 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);
|
gBitmap = ImageHelper.CreateEmpty(90, 90, PixelFormat.Format24bppRgb, BackColor, 96, 96);
|
||||||
pictureBox1.Image = gBitmap;
|
pictureBox1.Image = gBitmap;
|
||||||
|
|
|
@ -31,8 +31,7 @@ namespace Greenshot.Forms {
|
||||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
//
|
//
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
ToFront = true;
|
||||||
WindowDetails.ToForeground(Handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BugReportForm(string bugText) : this() {
|
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.Cursor = System.Windows.Forms.Cursors.Cross;
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||||
this.Name = "CaptureForm";
|
this.Name = "CaptureForm";
|
||||||
this.ShowIcon = false;
|
this.ShowIcon = true;
|
||||||
this.ShowInTaskbar = false;
|
this.ShowInTaskbar = false;
|
||||||
this.TopMost = true;
|
this.TopMost = true;
|
||||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.CaptureFormKeyDown);
|
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.CaptureFormKeyDown);
|
||||||
|
|
|
@ -123,6 +123,7 @@ namespace Greenshot.Forms {
|
||||||
LOG.Debug("Closing captureform");
|
LOG.Debug("Closing captureform");
|
||||||
WindowDetails.UnregisterIgnoreHandle(Handle);
|
WindowDetails.UnregisterIgnoreHandle(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This creates the capture form
|
/// This creates the capture form
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -130,7 +131,7 @@ namespace Greenshot.Forms {
|
||||||
/// <param name="windows"></param>
|
/// <param name="windows"></param>
|
||||||
public CaptureForm(ICapture capture, List<WindowDetails> windows) {
|
public CaptureForm(ICapture capture, List<WindowDetails> windows) {
|
||||||
if (_currentForm != null) {
|
if (_currentForm != null) {
|
||||||
LOG.Debug("Found currentForm, Closing already opened CaptureForm");
|
LOG.Warn("Found currentForm, Closing already opened CaptureForm");
|
||||||
_currentForm.Close();
|
_currentForm.Close();
|
||||||
_currentForm = null;
|
_currentForm = null;
|
||||||
Application.DoEvents();
|
Application.DoEvents();
|
||||||
|
@ -176,7 +177,7 @@ namespace Greenshot.Forms {
|
||||||
ResumeLayout();
|
ResumeLayout();
|
||||||
|
|
||||||
// Fix missing focus
|
// Fix missing focus
|
||||||
WindowDetails.ToForeground(Handle);
|
ToFront = true;
|
||||||
TopMost = true;
|
TopMost = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ namespace Greenshot.Forms {
|
||||||
public DropShadowSettingsForm(DropShadowEffect effect) {
|
public DropShadowSettingsForm(DropShadowEffect effect) {
|
||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
ShowSettings();
|
ShowSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,8 +162,6 @@ namespace Greenshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUI() {
|
private void updateUI() {
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
// Disable access to the settings, for feature #3521446
|
// Disable access to the settings, for feature #3521446
|
||||||
preferencesToolStripMenuItem.Visible = !coreConfiguration.DisableSettings;
|
preferencesToolStripMenuItem.Visible = !coreConfiguration.DisableSettings;
|
||||||
toolStripSeparator12.Visible = !coreConfiguration.DisableSettings;
|
toolStripSeparator12.Visible = !coreConfiguration.DisableSettings;
|
||||||
|
|
|
@ -270,6 +270,9 @@ namespace Greenshot {
|
||||||
return;
|
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
|
// From here on we continue starting Greenshot
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
@ -359,7 +362,6 @@ namespace Greenshot {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
notifyIcon.Icon = GreenshotResources.getGreenshotIcon();
|
notifyIcon.Icon = GreenshotResources.getGreenshotIcon();
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
// Disable access to the settings, for feature #3521446
|
// Disable access to the settings, for feature #3521446
|
||||||
contextmenu_settings.Visible = !_conf.DisableSettings;
|
contextmenu_settings.Visible = !_conf.DisableSettings;
|
||||||
|
@ -508,14 +510,20 @@ namespace Greenshot {
|
||||||
get {return contextMenu;}
|
get {return contextMenu;}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region hotkeys
|
|
||||||
protected override void WndProc(ref Message m) {
|
protected override void WndProc(ref Message m) {
|
||||||
if (HotkeyControl.HandleMessages(ref m)) {
|
if (HotkeyControl.HandleMessages(ref m)) {
|
||||||
return;
|
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>
|
/// <summary>
|
||||||
/// Helper method to cleanly register a hotkey
|
/// Helper method to cleanly register a hotkey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1223,14 +1231,27 @@ namespace Greenshot {
|
||||||
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
||||||
Exception exceptionToLog = e.ExceptionObject as Exception;
|
Exception exceptionToLog = e.ExceptionObject as Exception;
|
||||||
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
|
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();
|
new BugReportForm(exceptionText).ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
|
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
|
||||||
Exception exceptionToLog = e.Exception;
|
Exception exceptionToLog = e.Exception;
|
||||||
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
|
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();
|
new BugReportForm(exceptionText).ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace Greenshot.Forms {
|
||||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
//
|
//
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
checkbox_dontaskagain.Checked = false;
|
checkbox_dontaskagain.Checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ namespace Greenshot.Forms {
|
||||||
public ResizeSettingsForm(ResizeEffect effect) {
|
public ResizeSettingsForm(ResizeEffect effect) {
|
||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
value_pixel = Language.GetString("editor_resize_pixel");
|
value_pixel = Language.GetString("editor_resize_pixel");
|
||||||
value_percent = Language.GetString("editor_resize_percent");
|
value_percent = Language.GetString("editor_resize_percent");
|
||||||
combobox_width.Items.Add(value_pixel);
|
combobox_width.Items.Add(value_pixel);
|
||||||
|
|
|
@ -57,7 +57,6 @@ namespace Greenshot {
|
||||||
|
|
||||||
protected override void OnLoad(EventArgs e) {
|
protected override void OnLoad(EventArgs e) {
|
||||||
base.OnLoad(e);
|
base.OnLoad(e);
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
// Fix for Vista/XP differences
|
// Fix for Vista/XP differences
|
||||||
if (Environment.OSVersion.Version.Major >= 6) {
|
if (Environment.OSVersion.Version.Major >= 6) {
|
||||||
|
|
|
@ -30,7 +30,6 @@ namespace Greenshot.Forms {
|
||||||
public TornEdgeSettingsForm(TornEdgeEffect effect) {
|
public TornEdgeSettingsForm(TornEdgeEffect effect) {
|
||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
ShowSettings();
|
ShowSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
/*
|
/*
|
||||||
* Created by SharpDevelop.
|
* Greenshot - a free and open source screenshot tool
|
||||||
* User: jens
|
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
* Date: 09.04.2012
|
|
||||||
* Time: 19:24
|
|
||||||
*
|
*
|
||||||
* 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;
|
using GreenshotPlugin.Core;
|
||||||
|
@ -28,7 +40,7 @@ namespace Greenshot.Help
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LoadHelp() {
|
public static void LoadHelp() {
|
||||||
string uri = findOnlineHelpUrl(Language.CurrentLanguage);
|
string uri = FindOnlineHelpUrl(Language.CurrentLanguage);
|
||||||
if(uri == null) {
|
if(uri == null) {
|
||||||
uri = Language.HelpFilePath;
|
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>
|
/// <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 ret = null;
|
||||||
|
|
||||||
string extHelpUrlForCurrrentIETF = EXT_HELP_URL;
|
string extHelpUrlForCurrrentIETF = EXT_HELP_URL;
|
||||||
|
@ -45,12 +57,12 @@ namespace Greenshot.Help
|
||||||
extHelpUrlForCurrrentIETF += currentIETF.ToLower() + "/";
|
extHelpUrlForCurrrentIETF += currentIETF.ToLower() + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpStatusCode? httpStatusCode = getHttpStatus(extHelpUrlForCurrrentIETF);
|
HttpStatusCode? httpStatusCode = GetHttpStatus(extHelpUrlForCurrrentIETF);
|
||||||
if(httpStatusCode == HttpStatusCode.OK) {
|
if(httpStatusCode == HttpStatusCode.OK) {
|
||||||
ret = extHelpUrlForCurrrentIETF;
|
ret = extHelpUrlForCurrrentIETF;
|
||||||
} else if(httpStatusCode != null && !extHelpUrlForCurrrentIETF.Equals(EXT_HELP_URL)) {
|
} 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);
|
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) {
|
if(httpStatusCode == HttpStatusCode.OK) {
|
||||||
ret = EXT_HELP_URL;
|
ret = EXT_HELP_URL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,9 +80,9 @@ namespace Greenshot.Help
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">URL for which the HTTP status is to be checked</param>
|
/// <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>
|
/// <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 {
|
try {
|
||||||
HttpWebRequest req = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
HttpWebRequest req = NetworkHelper.CreateWebRequest(url);
|
||||||
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
|
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
|
||||||
return res.StatusCode;
|
return res.StatusCode;
|
||||||
} catch(WebException e) {
|
} catch(WebException e) {
|
||||||
|
|
|
@ -967,7 +967,13 @@ namespace Greenshot.Helpers {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
using (CaptureForm captureForm = new CaptureForm(_capture, _windows)) {
|
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) {
|
if (result == DialogResult.OK) {
|
||||||
_selectedCaptureWindow = captureForm.SelectedCaptureWindow;
|
_selectedCaptureWindow = captureForm.SelectedCaptureWindow;
|
||||||
_captureRect = captureForm.CaptureRectangle;
|
_captureRect = captureForm.CaptureRectangle;
|
||||||
|
@ -975,11 +981,11 @@ namespace Greenshot.Helpers {
|
||||||
if (_selectedCaptureWindow != null) {
|
if (_selectedCaptureWindow != null) {
|
||||||
_capture.CaptureDetails.Title = _selectedCaptureWindow.Text;
|
_capture.CaptureDetails.Title = _selectedCaptureWindow.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_captureRect.Height > 0 && _captureRect.Width > 0) {
|
if (_captureRect.Height > 0 && _captureRect.Width > 0) {
|
||||||
// Take the captureRect, this already is specified as bitmap coordinates
|
// Take the captureRect, this already is specified as bitmap coordinates
|
||||||
_capture.Crop(_captureRect);
|
_capture.Crop(_captureRect);
|
||||||
|
|
||||||
// save for re-capturing later and show recapture context menu option
|
// 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!
|
// Important here is that the location needs to be offsetted back to screen coordinates!
|
||||||
Rectangle tmpRectangle = _captureRect;
|
Rectangle tmpRectangle = _captureRect;
|
||||||
|
|
|
@ -18,30 +18,33 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
using GreenshotPlugin.UnmanagedHelpers;
|
|
||||||
using GreenshotPlugin.Core;
|
|
||||||
using Greenshot.IniFile;
|
using Greenshot.IniFile;
|
||||||
using Greenshot.Drawing;
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
namespace Greenshot.Helpers {
|
namespace Greenshot.Helpers
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of EnvironmentInfo.
|
/// Description of EnvironmentInfo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class EnvironmentInfo {
|
public static class EnvironmentInfo
|
||||||
|
{
|
||||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(EnvironmentInfo));
|
private static readonly ILog LOG = LogManager.GetLogger(typeof(EnvironmentInfo));
|
||||||
private static bool? isWindows = null;
|
private static bool? isWindows = null;
|
||||||
|
|
||||||
public static bool IsWindows {
|
public static bool IsWindows
|
||||||
get {
|
{
|
||||||
if (isWindows.HasValue) {
|
get
|
||||||
|
{
|
||||||
|
if (isWindows.HasValue)
|
||||||
|
{
|
||||||
return isWindows.Value;
|
return isWindows.Value;
|
||||||
}
|
}
|
||||||
isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win");
|
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.
|
// Class "ReflectionContext" exists from .NET 4.5 onwards.
|
||||||
return Type.GetType("System.Reflection.ReflectionContext", false) != null;
|
return Type.GetType("System.Reflection.ReflectionContext", false) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string EnvironmentToString(bool newline) {
|
public static string EnvironmentToString(bool newline)
|
||||||
|
{
|
||||||
StringBuilder environment = new StringBuilder();
|
StringBuilder environment = new StringBuilder();
|
||||||
environment.Append("Software version: " + Application.ProductVersion);
|
environment.Append("Software version: " + Application.ProductVersion);
|
||||||
if (IniConfig.IsPortable) {
|
if (IniConfig.IsPortable) {
|
||||||
environment.Append(" Portable");
|
environment.Append(" Portable");
|
||||||
}
|
}
|
||||||
environment.Append(" (" + OSInfo.Bits + " bit)");
|
environment.Append(" (" + OSInfo.Bits + " bit)");
|
||||||
|
|
||||||
if (newline) {
|
if (newline)
|
||||||
|
{
|
||||||
environment.AppendLine();
|
environment.AppendLine();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
environment.Append(", ");
|
environment.Append(", ");
|
||||||
}
|
}
|
||||||
environment.Append(".NET runtime version: " + Environment.Version);
|
environment.Append(".NET runtime version: " + Environment.Version);
|
||||||
if (IsNet45OrNewer()) {
|
if (IsNet45OrNewer())
|
||||||
|
{
|
||||||
environment.Append("+");
|
environment.Append("+");
|
||||||
|
|
||||||
}
|
}
|
||||||
if (newline) {
|
if (newline)
|
||||||
|
{
|
||||||
environment.AppendLine();
|
environment.AppendLine();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
environment.Append(", ");
|
environment.Append(", ");
|
||||||
}
|
}
|
||||||
environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
|
environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
|
||||||
|
|
||||||
if (IsWindows) {
|
if (IsWindows)
|
||||||
if (newline) {
|
{
|
||||||
|
if (newline)
|
||||||
|
{
|
||||||
environment.AppendLine();
|
environment.AppendLine();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
environment.Append(", ");
|
environment.Append(", ");
|
||||||
}
|
}
|
||||||
environment.Append(String.Format("OS: {0} {1} {2} (x{3}) {4}", OSInfo.Name, OSInfo.Edition, OSInfo.ServicePack, OSInfo.Bits, OSInfo.VersionString));
|
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();
|
environment.AppendLine();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
environment.Append(", ");
|
environment.Append(", ");
|
||||||
}
|
}
|
||||||
// Get some important information for fixing GDI related Problems
|
// Get some important information for fixing GDI related Problems
|
||||||
environment.Append("GDI object count: " + User32.GetGuiResourcesGDICount());
|
environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount());
|
||||||
if (newline) {
|
if (newline)
|
||||||
|
{
|
||||||
environment.AppendLine();
|
environment.AppendLine();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
environment.Append(", ");
|
environment.Append(", ");
|
||||||
}
|
}
|
||||||
environment.Append("User object count: " + User32.GetGuiResourcesUserCount());
|
environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount());
|
||||||
} else {
|
|
||||||
if (newline) {
|
|
||||||
environment.AppendLine();
|
|
||||||
} else {
|
|
||||||
environment.Append(", ");
|
|
||||||
}
|
|
||||||
environment.Append("OS: " + Environment.OSVersion.Platform.ToString());
|
|
||||||
}
|
}
|
||||||
if (newline) {
|
else
|
||||||
|
{
|
||||||
|
if (newline)
|
||||||
|
{
|
||||||
|
environment.AppendLine();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
environment.Append(", ");
|
||||||
|
}
|
||||||
|
environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform);
|
||||||
|
}
|
||||||
|
if (newline)
|
||||||
|
{
|
||||||
environment.AppendLine();
|
environment.AppendLine();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
environment.Append(", ");
|
environment.Append(", ");
|
||||||
}
|
}
|
||||||
environment.Append("Surface count: " + Surface.Count);
|
// TODO: Is this needed?
|
||||||
|
// environment.AppendFormat("Surface count: {0}", Surface.Count);
|
||||||
|
|
||||||
return environment.ToString();
|
return environment.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ExceptionToString(Exception ex) {
|
public static string ExceptionToString(Exception ex)
|
||||||
|
{
|
||||||
if (ex == null)
|
if (ex == null)
|
||||||
return "null\r\n";
|
return "null\r\n";
|
||||||
|
|
||||||
|
@ -125,44 +157,54 @@ namespace Greenshot.Helpers {
|
||||||
|
|
||||||
report.AppendLine("Exception: " + ex.GetType().ToString());
|
report.AppendLine("Exception: " + ex.GetType().ToString());
|
||||||
report.AppendLine("Message: " + ex.Message);
|
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();
|
||||||
report.AppendLine("Additional Information:");
|
report.AppendLine("Additional Information:");
|
||||||
foreach (object key in ex.Data.Keys) {
|
foreach (object key in ex.Data.Keys)
|
||||||
|
{
|
||||||
object data = ex.Data[key];
|
object data = ex.Data[key];
|
||||||
if (data != null) {
|
if (data != null)
|
||||||
|
{
|
||||||
report.AppendLine(key + " : " + data);
|
report.AppendLine(key + " : " + data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ex is ExternalException) {
|
if (ex is ExternalException)
|
||||||
|
{
|
||||||
// e.g. COMException
|
// e.g. COMException
|
||||||
report.AppendLine().AppendLine("ErrorCode: 0x" + (ex as ExternalException).ErrorCode.ToString("X"));
|
report.AppendLine().AppendLine("ErrorCode: 0x" + (ex as ExternalException).ErrorCode.ToString("X"));
|
||||||
}
|
}
|
||||||
|
|
||||||
report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace);
|
report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace);
|
||||||
|
|
||||||
if (ex is ReflectionTypeLoadException) {
|
if (ex is ReflectionTypeLoadException)
|
||||||
|
{
|
||||||
report.AppendLine().AppendLine("LoaderExceptions: ");
|
report.AppendLine().AppendLine("LoaderExceptions: ");
|
||||||
foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions) {
|
foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions)
|
||||||
|
{
|
||||||
report.AppendLine(cbE.Message);
|
report.AppendLine(cbE.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ex.InnerException != null) {
|
if (ex.InnerException != null)
|
||||||
|
{
|
||||||
report.AppendLine("--- InnerException: ---");
|
report.AppendLine("--- InnerException: ---");
|
||||||
report.AppendLine(ExceptionToString(ex.InnerException));
|
report.AppendLine(ExceptionToString(ex.InnerException));
|
||||||
}
|
}
|
||||||
return report.ToString();
|
return report.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string BuildReport(Exception exception) {
|
public static string BuildReport(Exception exception)
|
||||||
|
{
|
||||||
StringBuilder exceptionText = new StringBuilder();
|
StringBuilder exceptionText = new StringBuilder();
|
||||||
exceptionText.AppendLine(EnvironmentToString(true));
|
exceptionText.AppendLine(EnvironmentToString(true));
|
||||||
exceptionText.AppendLine(ExceptionToString(exception));
|
exceptionText.AppendLine(ExceptionToString(exception));
|
||||||
exceptionText.AppendLine("Configuration dump:");
|
exceptionText.AppendLine("Configuration dump:");
|
||||||
using (TextWriter writer = new StringWriter(exceptionText)) {
|
using (TextWriter writer = new StringWriter(exceptionText))
|
||||||
IniConfig.GetIniSection<CoreConfiguration>().Write(writer, true);
|
{
|
||||||
|
// TODO: Create summary of properties
|
||||||
|
//var iniConfig = IniConfig.Current.WriteToStreamAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
return exceptionText.ToString();
|
return exceptionText.ToString();
|
||||||
|
@ -173,13 +215,16 @@ namespace Greenshot.Helpers {
|
||||||
/// Provides detailed information about the host operating system.
|
/// Provides detailed information about the host operating system.
|
||||||
/// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
|
/// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public class OSInfo {
|
static public class OSInfo
|
||||||
|
{
|
||||||
#region BITS
|
#region BITS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the current application is 32 or 64-bit.
|
/// Determines if the current application is 32 or 64-bit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public int Bits {
|
static public int Bits
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return IntPtr.Size * 8;
|
return IntPtr.Size * 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,9 +235,12 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the edition of the operating system running on this computer.
|
/// Gets the edition of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public string Edition {
|
static public string Edition
|
||||||
get {
|
{
|
||||||
if (s_Edition != null) {
|
get
|
||||||
|
{
|
||||||
|
if (s_Edition != null)
|
||||||
|
{
|
||||||
return s_Edition; //***** RETURN *****//
|
return s_Edition; //***** RETURN *****//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,22 +250,30 @@ namespace Greenshot.Helpers {
|
||||||
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
||||||
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
||||||
|
|
||||||
if (GetVersionEx(ref osVersionInfo)) {
|
if (GetVersionEx(ref osVersionInfo))
|
||||||
|
{
|
||||||
int majorVersion = osVersion.Version.Major;
|
int majorVersion = osVersion.Version.Major;
|
||||||
int minorVersion = osVersion.Version.Minor;
|
int minorVersion = osVersion.Version.Minor;
|
||||||
byte productType = osVersionInfo.wProductType;
|
byte productType = osVersionInfo.wProductType;
|
||||||
short suiteMask = osVersionInfo.wSuiteMask;
|
short suiteMask = osVersionInfo.wSuiteMask;
|
||||||
|
|
||||||
#region VERSION 4
|
#region VERSION 4
|
||||||
if (majorVersion == 4) {
|
if (majorVersion == 4)
|
||||||
if (productType == VER_NT_WORKSTATION) {
|
{
|
||||||
|
if (productType == VER_NT_WORKSTATION)
|
||||||
|
{
|
||||||
// Windows NT 4.0 Workstation
|
// Windows NT 4.0 Workstation
|
||||||
edition = "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
|
// Windows NT 4.0 Server Enterprise
|
||||||
edition = "Enterprise Server";
|
edition = "Enterprise Server";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Windows NT 4.0 Server
|
// Windows NT 4.0 Server
|
||||||
edition = "Standard Server";
|
edition = "Standard Server";
|
||||||
}
|
}
|
||||||
|
@ -226,38 +282,60 @@ namespace Greenshot.Helpers {
|
||||||
#endregion VERSION 4
|
#endregion VERSION 4
|
||||||
|
|
||||||
#region VERSION 5
|
#region VERSION 5
|
||||||
else if (majorVersion == 5) {
|
else if (majorVersion == 5)
|
||||||
if (productType == VER_NT_WORKSTATION) {
|
{
|
||||||
if ((suiteMask & VER_SUITE_PERSONAL) != 0) {
|
if (productType == VER_NT_WORKSTATION)
|
||||||
|
{
|
||||||
|
if ((suiteMask & VER_SUITE_PERSONAL) != 0)
|
||||||
|
{
|
||||||
// Windows XP Home Edition
|
// Windows XP Home Edition
|
||||||
edition = "Home";
|
edition = "Home";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Windows XP / Windows 2000 Professional
|
// Windows XP / Windows 2000 Professional
|
||||||
edition = "Professional";
|
edition = "Professional";
|
||||||
}
|
}
|
||||||
} else if (productType == VER_NT_SERVER) {
|
}
|
||||||
if (minorVersion == 0) {
|
else if (productType == VER_NT_SERVER)
|
||||||
if ((suiteMask & VER_SUITE_DATACENTER) != 0) {
|
{
|
||||||
|
if (minorVersion == 0)
|
||||||
|
{
|
||||||
|
if ((suiteMask & VER_SUITE_DATACENTER) != 0)
|
||||||
|
{
|
||||||
// Windows 2000 Datacenter Server
|
// Windows 2000 Datacenter Server
|
||||||
edition = "Datacenter Server";
|
edition = "Datacenter Server";
|
||||||
} else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) {
|
}
|
||||||
|
else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
|
||||||
|
{
|
||||||
// Windows 2000 Advanced Server
|
// Windows 2000 Advanced Server
|
||||||
edition = "Advanced Server";
|
edition = "Advanced Server";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Windows 2000 Server
|
// Windows 2000 Server
|
||||||
edition = "Server";
|
edition = "Server";
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if ((suiteMask & VER_SUITE_DATACENTER) != 0) {
|
else
|
||||||
|
{
|
||||||
|
if ((suiteMask & VER_SUITE_DATACENTER) != 0)
|
||||||
|
{
|
||||||
// Windows Server 2003 Datacenter Edition
|
// Windows Server 2003 Datacenter Edition
|
||||||
edition = "Datacenter";
|
edition = "Datacenter";
|
||||||
} else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) {
|
}
|
||||||
|
else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
|
||||||
|
{
|
||||||
// Windows Server 2003 Enterprise Edition
|
// Windows Server 2003 Enterprise Edition
|
||||||
edition = "Enterprise";
|
edition = "Enterprise";
|
||||||
} else if ((suiteMask & VER_SUITE_BLADE) != 0) {
|
}
|
||||||
|
else if ((suiteMask & VER_SUITE_BLADE) != 0)
|
||||||
|
{
|
||||||
// Windows Server 2003 Web Edition
|
// Windows Server 2003 Web Edition
|
||||||
edition = "Web Edition";
|
edition = "Web Edition";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Windows Server 2003 Standard Edition
|
// Windows Server 2003 Standard Edition
|
||||||
edition = "Standard";
|
edition = "Standard";
|
||||||
}
|
}
|
||||||
|
@ -267,10 +345,13 @@ namespace Greenshot.Helpers {
|
||||||
#endregion VERSION 5
|
#endregion VERSION 5
|
||||||
|
|
||||||
#region VERSION 6
|
#region VERSION 6
|
||||||
else if (majorVersion == 6) {
|
else if (majorVersion == 6)
|
||||||
|
{
|
||||||
int ed;
|
int ed;
|
||||||
if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.wServicePackMajor, osVersionInfo.wServicePackMinor, out ed)) {
|
if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.wServicePackMajor, osVersionInfo.wServicePackMinor, out ed))
|
||||||
switch (ed) {
|
{
|
||||||
|
switch (ed)
|
||||||
|
{
|
||||||
case PRODUCT_BUSINESS:
|
case PRODUCT_BUSINESS:
|
||||||
edition = "Business";
|
edition = "Business";
|
||||||
break;
|
break;
|
||||||
|
@ -399,9 +480,12 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name of the operating system running on this computer.
|
/// Gets the name of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public string Name {
|
static public string Name
|
||||||
get {
|
{
|
||||||
if (s_Name != null) {
|
get
|
||||||
|
{
|
||||||
|
if (s_Name != null)
|
||||||
|
{
|
||||||
return s_Name; //***** RETURN *****//
|
return s_Name; //***** RETURN *****//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,27 +495,37 @@ namespace Greenshot.Helpers {
|
||||||
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
||||||
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
||||||
|
|
||||||
if (GetVersionEx(ref osVersionInfo)) {
|
if (GetVersionEx(ref osVersionInfo))
|
||||||
|
{
|
||||||
int majorVersion = osVersion.Version.Major;
|
int majorVersion = osVersion.Version.Major;
|
||||||
int minorVersion = osVersion.Version.Minor;
|
int minorVersion = osVersion.Version.Minor;
|
||||||
byte productType = osVersionInfo.wProductType;
|
byte productType = osVersionInfo.wProductType;
|
||||||
short suiteMask = osVersionInfo.wSuiteMask;
|
short suiteMask = osVersionInfo.wSuiteMask;
|
||||||
switch (osVersion.Platform) {
|
switch (osVersion.Platform)
|
||||||
|
{
|
||||||
case PlatformID.Win32Windows:
|
case PlatformID.Win32Windows:
|
||||||
if (majorVersion == 4) {
|
if (majorVersion == 4)
|
||||||
|
{
|
||||||
string csdVersion = osVersionInfo.szCSDVersion;
|
string csdVersion = osVersionInfo.szCSDVersion;
|
||||||
switch (minorVersion) {
|
switch (minorVersion)
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (csdVersion == "B" || csdVersion == "C") {
|
if (csdVersion == "B" || csdVersion == "C")
|
||||||
|
{
|
||||||
name = "Windows 95 OSR2";
|
name = "Windows 95 OSR2";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
name = "Windows 95";
|
name = "Windows 95";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
if (csdVersion == "A") {
|
if (csdVersion == "A")
|
||||||
|
{
|
||||||
name = "Windows 98 Second Edition";
|
name = "Windows 98 Second Edition";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
name = "Windows 98";
|
name = "Windows 98";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -442,12 +536,14 @@ namespace Greenshot.Helpers {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PlatformID.Win32NT:
|
case PlatformID.Win32NT:
|
||||||
switch (majorVersion) {
|
switch (majorVersion)
|
||||||
|
{
|
||||||
case 3:
|
case 3:
|
||||||
name = "Windows NT 3.51";
|
name = "Windows NT 3.51";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
switch (productType) {
|
switch (productType)
|
||||||
|
{
|
||||||
case 1:
|
case 1:
|
||||||
name = "Windows NT 4.0";
|
name = "Windows NT 4.0";
|
||||||
break;
|
break;
|
||||||
|
@ -457,12 +553,14 @@ namespace Greenshot.Helpers {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
switch (minorVersion) {
|
switch (minorVersion)
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
name = "Windows 2000";
|
name = "Windows 2000";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
switch (suiteMask) {
|
switch (suiteMask)
|
||||||
|
{
|
||||||
case 0x0200:
|
case 0x0200:
|
||||||
name = "Windows XP Professional";
|
name = "Windows XP Professional";
|
||||||
break;
|
break;
|
||||||
|
@ -472,7 +570,8 @@ namespace Greenshot.Helpers {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
switch (suiteMask) {
|
switch (suiteMask)
|
||||||
|
{
|
||||||
case 0x0200:
|
case 0x0200:
|
||||||
name = "Windows XP Professional x64";
|
name = "Windows XP Professional x64";
|
||||||
break;
|
break;
|
||||||
|
@ -496,9 +595,11 @@ namespace Greenshot.Helpers {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
switch (minorVersion) {
|
switch (minorVersion)
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
switch (productType) {
|
switch (productType)
|
||||||
|
{
|
||||||
case 3:
|
case 3:
|
||||||
name = "Windows Server 2008";
|
name = "Windows Server 2008";
|
||||||
break;
|
break;
|
||||||
|
@ -508,7 +609,8 @@ namespace Greenshot.Helpers {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
switch (productType) {
|
switch (productType)
|
||||||
|
{
|
||||||
case 3:
|
case 3:
|
||||||
name = "Windows Server 2008 R2";
|
name = "Windows Server 2008 R2";
|
||||||
break;
|
break;
|
||||||
|
@ -520,8 +622,14 @@ namespace Greenshot.Helpers {
|
||||||
case 2:
|
case 2:
|
||||||
name = "Windows 8";
|
name = "Windows 8";
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
name = "Windows 8.1";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 10:
|
||||||
|
name = "Windows 10";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -553,7 +661,8 @@ namespace Greenshot.Helpers {
|
||||||
|
|
||||||
#region OSVERSIONINFOEX
|
#region OSVERSIONINFOEX
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
private struct OSVERSIONINFOEX {
|
private struct OSVERSIONINFOEX
|
||||||
|
{
|
||||||
public int dwOSVersionInfoSize;
|
public int dwOSVersionInfoSize;
|
||||||
public int dwMajorVersion;
|
public int dwMajorVersion;
|
||||||
public int dwMinorVersion;
|
public int dwMinorVersion;
|
||||||
|
@ -629,14 +738,17 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the service pack information of the operating system running on this computer.
|
/// Gets the service pack information of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public string ServicePack {
|
static public string ServicePack
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
string servicePack = String.Empty;
|
string servicePack = String.Empty;
|
||||||
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
|
||||||
|
|
||||||
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
|
||||||
|
|
||||||
if (GetVersionEx(ref osVersionInfo)) {
|
if (GetVersionEx(ref osVersionInfo))
|
||||||
|
{
|
||||||
servicePack = osVersionInfo.szCSDVersion;
|
servicePack = osVersionInfo.szCSDVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,8 +762,10 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the build version number of the operating system running on this computer.
|
/// Gets the build version number of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int BuildVersion {
|
public static int BuildVersion
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return Environment.OSVersion.Version.Build;
|
return Environment.OSVersion.Version.Build;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -662,8 +776,10 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the full version string of the operating system running on this computer.
|
/// Gets the full version string of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public string VersionString {
|
static public string VersionString
|
||||||
get {
|
{
|
||||||
|
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);
|
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>
|
/// <summary>
|
||||||
/// Gets the full version of the operating system running on this computer.
|
/// Gets the full version of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public Version Version {
|
static public Version Version
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return Environment.OSVersion.Version;
|
return Environment.OSVersion.Version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,8 +803,10 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the major version number of the operating system running on this computer.
|
/// Gets the major version number of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public int MajorVersion {
|
static public int MajorVersion
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return Environment.OSVersion.Version.Major;
|
return Environment.OSVersion.Version.Major;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -696,8 +816,10 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the minor version number of the operating system running on this computer.
|
/// Gets the minor version number of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public int MinorVersion {
|
static public int MinorVersion
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return Environment.OSVersion.Version.Minor;
|
return Environment.OSVersion.Version.Minor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,12 +829,14 @@ namespace Greenshot.Helpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the revision version number of the operating system running on this computer.
|
/// Gets the revision version number of the operating system running on this computer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static public int RevisionVersion {
|
static public int RevisionVersion
|
||||||
get {
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
return Environment.OSVersion.Version.Revision;
|
return Environment.OSVersion.Version.Revision;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion REVISION
|
#endregion REVISION
|
||||||
#endregion VERSION
|
#endregion VERSION
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,14 +9,16 @@
|
||||||
</asmv3:application>
|
</asmv3:application>
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
<application>
|
<application>
|
||||||
<!--The ID below indicates app support for Windows Vista -->
|
<!-- Windows 10 -->
|
||||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
<!--The ID below indicates app support for Windows 7 -->
|
<!-- Windows 8.1 -->
|
||||||
<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 -->
|
|
||||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
<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>
|
</application>
|
||||||
</compatibility>
|
</compatibility>
|
||||||
<!-- Set UAC level to "asInvoker" and disable registry virtualization -->
|
<!-- 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@
|
@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:
|
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-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.
|
* 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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.IniFile;
|
using Greenshot.IniFile;
|
||||||
using GreenshotPlugin.Core;
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace GreenshotBoxPlugin {
|
namespace GreenshotBoxPlugin {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -38,10 +40,37 @@ namespace GreenshotBoxPlugin {
|
||||||
public bool AfterUploadLinkToClipBoard;
|
public bool AfterUploadLinkToClipBoard;
|
||||||
|
|
||||||
[IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")]
|
[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 = "")]
|
[IniProperty("RefreshToken", Description = "Box authorization refresh Token", Encrypted = true)]
|
||||||
public string BoxToken;
|
public string RefreshToken {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Not stored
|
||||||
|
/// </summary>
|
||||||
|
public string AccessToken {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Not stored
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset AccessTokenExpires {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A form for token
|
/// A form for token
|
||||||
|
|
|
@ -18,16 +18,14 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.Collections.Generic;
|
||||||
using System.Drawing;
|
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.IO;
|
||||||
|
using System.Runtime.Serialization.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace GreenshotBoxPlugin {
|
namespace GreenshotBoxPlugin {
|
||||||
|
|
||||||
|
@ -37,101 +35,24 @@ namespace GreenshotBoxPlugin {
|
||||||
public static class BoxUtils {
|
public static class BoxUtils {
|
||||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxUtils));
|
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxUtils));
|
||||||
private static readonly BoxConfiguration Config = IniConfig.GetIniSection<BoxConfiguration>();
|
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 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 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>
|
/// <summary>
|
||||||
/// Download a url response as string
|
/// Put 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
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
/// <param name="content"></param>
|
/// <param name="content"></param>
|
||||||
|
/// <param name="settings">OAuth2Settings</param>
|
||||||
/// <returns>response</returns>
|
/// <returns>response</returns>
|
||||||
public static string HttpPut(string url, string content) {
|
public static string HttpPut(string url, string content, OAuth2Settings settings) {
|
||||||
var webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
var webRequest= OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.PUT, url, settings);
|
||||||
webRequest.Method = "PUT";
|
|
||||||
webRequest.KeepAlive = true;
|
|
||||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
|
||||||
webRequest.Headers.Add("Authorization", "Bearer " + Config.BoxToken);
|
|
||||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||||
using (var requestStream = webRequest.GetRequestStream()) {
|
using (var requestStream = webRequest.GetRequestStream()) {
|
||||||
requestStream.Write(data, 0, data.Length);
|
requestStream.Write(data, 0, data.Length);
|
||||||
}
|
}
|
||||||
return NetworkHelper.GetResponse(webRequest);
|
return NetworkHelper.GetResponseAsString(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -143,45 +64,52 @@ namespace GreenshotBoxPlugin {
|
||||||
/// <param name="filename">Filename of box upload</param>
|
/// <param name="filename">Filename of box upload</param>
|
||||||
/// <returns>url to uploaded image</returns>
|
/// <returns>url to uploaded image</returns>
|
||||||
public static string UploadToBox(SurfaceContainer image, string title, string filename) {
|
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>();
|
IDictionary<string, object> parameters = new Dictionary<string, object>();
|
||||||
parameters.Add("filename", image);
|
parameters.Add("file", image);
|
||||||
parameters.Add("parent_id", folderId);
|
parameters.Add("parent_id", Config.FolderId);
|
||||||
|
|
||||||
var response = "";
|
NetworkHelper.WriteMultipartFormData(webRequest, parameters);
|
||||||
try {
|
|
||||||
response = HttpPost(UploadFileUri, parameters);
|
var response = NetworkHelper.GetResponseAsString(webRequest);
|
||||||
} catch (WebException ex) {
|
|
||||||
if (ex.Status == WebExceptionStatus.ProtocolError) {
|
|
||||||
Config.BoxToken = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.DebugFormat("Box response: {0}", response);
|
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);
|
var upload = JsonSerializer.Deserialize<Upload>(response);
|
||||||
if (upload == null || upload.Entries == null || upload.Entries.Count == 0) return null;
|
if (upload == null || upload.Entries == null || upload.Entries.Count == 0) return null;
|
||||||
|
|
||||||
if (Config.UseSharedLink) {
|
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);
|
var file = JsonSerializer.Deserialize<FileEntry>(filesResponse);
|
||||||
return file.SharedLink.Url;
|
return file.SharedLink.Url;
|
||||||
}
|
}
|
||||||
return string.Format("http://www.box.com/files/0/f/0/1/f_{0}", upload.Entries[0].Id);
|
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();
|
InitializeComponent();
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using GreenshotDropboxPlugin.Forms;
|
using GreenshotDropboxPlugin.Forms;
|
||||||
|
@ -39,7 +40,6 @@ namespace GreenshotDropboxPlugin {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ namespace ExternalCommand {
|
||||||
if (config.OutputToClipboard) {
|
if (config.OutputToClipboard) {
|
||||||
ClipboardHelper.SetClipboardData(output);
|
ClipboardHelper.SetClipboardData(output);
|
||||||
}
|
}
|
||||||
if (uriMatches != null && uriMatches.Count >= 0) {
|
if (uriMatches != null && uriMatches.Count > 0) {
|
||||||
exportInformation.Uri = uriMatches[0].Groups[1].Value;
|
exportInformation.Uri = uriMatches[0].Groups[1].Value;
|
||||||
LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
|
LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
|
||||||
if (config.UriToClipboard) {
|
if (config.UriToClipboard) {
|
||||||
|
@ -134,10 +134,10 @@ namespace ExternalCommand {
|
||||||
exportInformation.ExportMade = false;
|
exportInformation.ExportMade = false;
|
||||||
exportInformation.ErrorMessage = error;
|
exportInformation.ErrorMessage = error;
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
|
|
||||||
exportInformation.ExportMade = false;
|
exportInformation.ExportMade = false;
|
||||||
exportInformation.ErrorMessage = ex.Message;
|
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.
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
//
|
//
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
AcceptButton = buttonOk;
|
AcceptButton = buttonOk;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
UpdateView();
|
UpdateView();
|
||||||
|
|
|
@ -38,7 +38,6 @@ namespace ExternalCommand {
|
||||||
|
|
||||||
public SettingsFormDetail(string commando) {
|
public SettingsFormDetail(string commando) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
AcceptButton = buttonOk;
|
AcceptButton = buttonOk;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
this.commando = commando;
|
this.commando = commando;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using GreenshotPlugin.Controls;
|
using GreenshotPlugin.Controls;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ namespace GreenshotFlickrPlugin {
|
||||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
//
|
//
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,15 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
|
||||||
namespace GreenshotImgurPlugin {
|
namespace GreenshotImgurPlugin {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class is needed for design-time resolving of the language files
|
/// This class is needed for design-time resolving of the language files
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ImgurForm : GreenshotPlugin.Controls.GreenshotForm {
|
public class ImgurForm : GreenshotForm {
|
||||||
public ImgurForm() : base() {
|
public ImgurForm() : base() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@ namespace GreenshotImgurPlugin
|
||||||
this.finishedButton.TabIndex = 11;
|
this.finishedButton.TabIndex = 11;
|
||||||
this.finishedButton.Text = "Finished";
|
this.finishedButton.Text = "Finished";
|
||||||
this.finishedButton.UseVisualStyleBackColor = true;
|
this.finishedButton.UseVisualStyleBackColor = true;
|
||||||
|
this.finishedButton.Click += new System.EventHandler(this.FinishedButtonClick);
|
||||||
//
|
//
|
||||||
// clipboardButton
|
// clipboardButton
|
||||||
//
|
//
|
||||||
|
|
|
@ -53,7 +53,6 @@ namespace GreenshotImgurPlugin {
|
||||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
//
|
//
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
AcceptButton = finishedButton;
|
AcceptButton = finishedButton;
|
||||||
CancelButton = finishedButton;
|
CancelButton = finishedButton;
|
||||||
// Init sorting
|
// Init sorting
|
||||||
|
@ -168,6 +167,11 @@ namespace GreenshotImgurPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FinishedButtonClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
private void OpenButtonClick(object sender, EventArgs e) {
|
private void OpenButtonClick(object sender, EventArgs e) {
|
||||||
if (listview_imgur_uploads.SelectedItems != null && listview_imgur_uploads.SelectedItems.Count > 0) {
|
if (listview_imgur_uploads.SelectedItems != null && listview_imgur_uploads.SelectedItems.Count > 0) {
|
||||||
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) {
|
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) {
|
||||||
|
|
|
@ -35,7 +35,6 @@ namespace GreenshotImgurPlugin {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
ImgurUtils.LoadHistory();
|
ImgurUtils.LoadHistory();
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,11 @@ namespace GreenshotImgurPlugin {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[IniSection("Imgur", Description="Greenshot Imgur Plugin configuration")]
|
[IniSection("Imgur", Description="Greenshot Imgur Plugin configuration")]
|
||||||
public class ImgurConfiguration : IniSection {
|
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;
|
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")]
|
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
|
||||||
public OutputFormat UploadFormat;
|
public OutputFormat UploadFormat;
|
||||||
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
|
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
|
||||||
|
|
|
@ -143,10 +143,15 @@ namespace GreenshotImgurPlugin
|
||||||
try {
|
try {
|
||||||
XmlDocument doc = new XmlDocument();
|
XmlDocument doc = new XmlDocument();
|
||||||
doc.LoadXml(response);
|
doc.LoadXml(response);
|
||||||
XmlNodeList nodes = doc.GetElementsByTagName("hash");
|
XmlNodeList nodes = doc.GetElementsByTagName("id");
|
||||||
if(nodes.Count > 0) {
|
if(nodes.Count > 0) {
|
||||||
imgurInfo.Hash = nodes.Item(0).InnerText;
|
imgurInfo.Hash = nodes.Item(0).InnerText;
|
||||||
}
|
}
|
||||||
|
nodes = doc.GetElementsByTagName("hash");
|
||||||
|
if (nodes.Count > 0)
|
||||||
|
{
|
||||||
|
imgurInfo.Hash = nodes.Item(0).InnerText;
|
||||||
|
}
|
||||||
nodes = doc.GetElementsByTagName("deletehash");
|
nodes = doc.GetElementsByTagName("deletehash");
|
||||||
if(nodes.Count > 0) {
|
if(nodes.Count > 0) {
|
||||||
imgurInfo.DeleteHash = nodes.Item(0).InnerText;
|
imgurInfo.DeleteHash = nodes.Item(0).InnerText;
|
||||||
|
@ -161,16 +166,41 @@ namespace GreenshotImgurPlugin
|
||||||
}
|
}
|
||||||
nodes = doc.GetElementsByTagName("datetime");
|
nodes = doc.GetElementsByTagName("datetime");
|
||||||
if(nodes.Count > 0) {
|
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");
|
nodes = doc.GetElementsByTagName("original");
|
||||||
if(nodes.Count > 0) {
|
if(nodes.Count > 0) {
|
||||||
imgurInfo.Original = nodes.Item(0).InnerText;
|
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");
|
nodes = doc.GetElementsByTagName("imgur_page");
|
||||||
if(nodes.Count > 0) {
|
if (nodes.Count > 0)
|
||||||
|
{
|
||||||
imgurInfo.Page = nodes.Item(0).InnerText;
|
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");
|
nodes = doc.GetElementsByTagName("small_square");
|
||||||
if(nodes.Count > 0) {
|
if(nodes.Count > 0) {
|
||||||
imgurInfo.SmallSquare = nodes.Item(0).InnerText;
|
imgurInfo.SmallSquare = nodes.Item(0).InnerText;
|
||||||
|
|
|
@ -31,14 +31,15 @@ namespace GreenshotImgurPlugin {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of ImgurUtils.
|
/// Description of ImgurUtils.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ImgurUtils {
|
public static class ImgurUtils {
|
||||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(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 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() {
|
public static void LoadHistory() {
|
||||||
if (config.runtimeImgurHistory.Count == config.ImgurUploadHistory.Count) {
|
if (config.runtimeImgurHistory.Count == config.ImgurUploadHistory.Count) {
|
||||||
return;
|
return;
|
||||||
|
@ -57,9 +58,9 @@ namespace GreenshotImgurPlugin {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ImgurInfo imgurInfo = ImgurUtils.RetrieveImgurInfo(hash, config.ImgurUploadHistory[hash]);
|
ImgurInfo imgurInfo = RetrieveImgurInfo(hash, config.ImgurUploadHistory[hash]);
|
||||||
if (imgurInfo != null) {
|
if (imgurInfo != null) {
|
||||||
ImgurUtils.RetrieveImgurThumbnail(imgurInfo);
|
RetrieveImgurThumbnail(imgurInfo);
|
||||||
config.runtimeImgurHistory.Add(hash, imgurInfo);
|
config.runtimeImgurHistory.Add(hash, imgurInfo);
|
||||||
} else {
|
} else {
|
||||||
LOG.DebugFormat("Deleting not found ImgUr {0} from config.", hash);
|
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>
|
/// <summary>
|
||||||
/// Do the actual upload to Imgur
|
/// Do the actual upload to Imgur
|
||||||
/// For more details on the available parameters, see: http://api.imgur.com/resources_anon
|
/// For more details on the available parameters, see: http://api.imgur.com/resources_anon
|
||||||
|
@ -113,11 +122,12 @@ namespace GreenshotImgurPlugin {
|
||||||
string responseString = null;
|
string responseString = null;
|
||||||
if (config.AnonymousAccess) {
|
if (config.AnonymousAccess) {
|
||||||
// add key, we only use the other parameters for the AnonymousAccess
|
// add key, we only use the other parameters for the AnonymousAccess
|
||||||
otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
|
//otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
|
||||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(config.ImgurApiUrl + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters));
|
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST);
|
||||||
webRequest.Method = "POST";
|
webRequest.ContentType = "image/" + outputSettings.Format;
|
||||||
webRequest.ContentType = "image/" + outputSettings.Format.ToString();
|
|
||||||
webRequest.ServicePoint.Expect100Continue = false;
|
webRequest.ServicePoint.Expect100Continue = false;
|
||||||
|
|
||||||
|
SetClientId(webRequest);
|
||||||
try {
|
try {
|
||||||
using (var requestStream = webRequest.GetRequestStream()) {
|
using (var requestStream = webRequest.GetRequestStream()) {
|
||||||
ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
|
ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
|
||||||
|
@ -127,7 +137,7 @@ namespace GreenshotImgurPlugin {
|
||||||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
||||||
responseString = reader.ReadToEnd();
|
responseString = reader.ReadToEnd();
|
||||||
}
|
}
|
||||||
LogCredits(response);
|
LogRateLimitInfo(response);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.Error("Upload to imgur gave an exeption: ", ex);
|
LOG.Error("Upload to imgur gave an exeption: ", ex);
|
||||||
|
@ -174,34 +184,43 @@ namespace GreenshotImgurPlugin {
|
||||||
return ImgurInfo.ParseResponse(responseString);
|
return ImgurInfo.ParseResponse(responseString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve the thumbnail of an imgur image
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imgurInfo"></param>
|
||||||
public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo) {
|
public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo) {
|
||||||
if (imgurInfo.SmallSquare == null) {
|
if (imgurInfo.SmallSquare == null) {
|
||||||
LOG.Warn("Imgur URL was null, not retrieving thumbnail.");
|
LOG.Warn("Imgur URL was null, not retrieving thumbnail.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare);
|
LOG.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare);
|
||||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(imgurInfo.SmallSquare);
|
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SMALL_URL_PATTERN, imgurInfo.Hash), HTTPMethod.GET);
|
||||||
webRequest.Method = "GET";
|
|
||||||
webRequest.ServicePoint.Expect100Continue = false;
|
webRequest.ServicePoint.Expect100Continue = false;
|
||||||
|
SetClientId(webRequest);
|
||||||
using (WebResponse response = webRequest.GetResponse()) {
|
using (WebResponse response = webRequest.GetResponse()) {
|
||||||
LogCredits(response);
|
LogRateLimitInfo(response);
|
||||||
Stream responseStream = response.GetResponseStream();
|
Stream responseStream = response.GetResponseStream();
|
||||||
imgurInfo.Image = Image.FromStream(responseStream);
|
imgurInfo.Image = Image.FromStream(responseStream);
|
||||||
}
|
}
|
||||||
return;
|
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) {
|
public static ImgurInfo RetrieveImgurInfo(string hash, string deleteHash) {
|
||||||
string url = config.ImgurApiUrl + "/image/" + hash;
|
string url = config.ImgurApiUrl + "/image/" + hash;
|
||||||
LOG.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url);
|
LOG.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url);
|
||||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
|
||||||
webRequest.Method = "GET";
|
|
||||||
webRequest.ServicePoint.Expect100Continue = false;
|
webRequest.ServicePoint.Expect100Continue = false;
|
||||||
|
SetClientId(webRequest);
|
||||||
string responseString;
|
string responseString;
|
||||||
try {
|
try {
|
||||||
using (WebResponse response = webRequest.GetResponse()) {
|
using (WebResponse response = webRequest.GetResponse()) {
|
||||||
LogCredits(response);
|
LogRateLimitInfo(response);
|
||||||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
||||||
responseString = reader.ReadToEnd();
|
responseString = reader.ReadToEnd();
|
||||||
}
|
}
|
||||||
|
@ -220,20 +239,21 @@ namespace GreenshotImgurPlugin {
|
||||||
return imgurInfo;
|
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) {
|
public static void DeleteImgurImage(ImgurInfo imgurInfo) {
|
||||||
LOG.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash);
|
LOG.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
string url = config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash;
|
string url = config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash;
|
||||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
|
||||||
|
|
||||||
//webRequest.Method = "DELETE";
|
|
||||||
webRequest.Method = "GET";
|
|
||||||
webRequest.ServicePoint.Expect100Continue = false;
|
webRequest.ServicePoint.Expect100Continue = false;
|
||||||
|
SetClientId(webRequest);
|
||||||
string responseString;
|
string responseString;
|
||||||
using (WebResponse response = webRequest.GetResponse()) {
|
using (WebResponse response = webRequest.GetResponse()) {
|
||||||
LogCredits(response);
|
LogRateLimitInfo(response);
|
||||||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) {
|
||||||
responseString = reader.ReadToEnd();
|
responseString = reader.ReadToEnd();
|
||||||
}
|
}
|
||||||
|
@ -252,17 +272,42 @@ namespace GreenshotImgurPlugin {
|
||||||
config.ImgurUploadHistory.Remove(imgurInfo.Hash);
|
config.ImgurUploadHistory.Remove(imgurInfo.Hash);
|
||||||
imgurInfo.Image = null;
|
imgurInfo.Image = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LogCredits(WebResponse response) {
|
/// <summary>
|
||||||
try {
|
/// Helper for logging
|
||||||
int credits = 0;
|
/// </summary>
|
||||||
if (int.TryParse(response.Headers["X-RateLimit-Remaining"], out credits)) {
|
/// <param name="nameValues"></param>
|
||||||
config.Credits = credits;
|
/// <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"]);
|
LogHeader(nameValues, "X-RateLimit-Limit");
|
||||||
|
LogHeader(nameValues, "X-RateLimit-Remaining");
|
||||||
} catch {}
|
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();
|
InitializeComponent();
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
|
||||||
namespace GreenshotOCR {
|
namespace GreenshotOCR {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class is needed for design-time resolving of the language files
|
/// This class is needed for design-time resolving of the language files
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OCRForm : GreenshotPlugin.Controls.GreenshotForm {
|
public class OCRForm : GreenshotForm {
|
||||||
public OCRForm() : base() {
|
public OCRForm() : base() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ namespace GreenshotOCR {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
this.Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
comboBox_languages.Items.Clear();
|
comboBox_languages.Items.Clear();
|
||||||
int index=0;
|
int index=0;
|
||||||
|
|
|
@ -35,7 +35,6 @@ namespace GreenshotPhotobucketPlugin {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ namespace GreenshotPicasaPlugin {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
CancelButton = buttonCancel;
|
CancelButton = buttonCancel;
|
||||||
AcceptButton = buttonOK;
|
AcceptButton = buttonOK;
|
||||||
Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.IniFile;
|
using Greenshot.IniFile;
|
||||||
using GreenshotPlugin.Core;
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace GreenshotPicasaPlugin {
|
namespace GreenshotPicasaPlugin {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -36,11 +37,45 @@ namespace GreenshotPicasaPlugin {
|
||||||
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Picasa link to clipboard.", DefaultValue = "true")]
|
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Picasa link to clipboard.", DefaultValue = "true")]
|
||||||
public bool AfterUploadLinkToClipBoard;
|
public bool AfterUploadLinkToClipBoard;
|
||||||
|
|
||||||
[IniProperty("PicasaToken", Description = "Picasa Token", Encrypted = true)]
|
[IniProperty("AddFilename", Description = "Is the filename passed on to Picasa", DefaultValue = "False")]
|
||||||
public string PicasaToken;
|
public bool AddFilename {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
[IniProperty("PicasaTokenSecret", Description = "PicasaTokenSecret", Encrypted = true)]
|
[IniProperty("UploadUser", Description = "The picasa user to upload to", DefaultValue = "default")]
|
||||||
public string PicasaTokenSecret;
|
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>
|
/// <summary>
|
||||||
/// A form for token
|
/// A form for token
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace GreenshotPicasaPlugin {
|
||||||
/// You can set your own values here
|
/// You can set your own values here
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class PicasaCredentials {
|
public static class PicasaCredentials {
|
||||||
public static string ConsumerKey = "@credentials_picasa_consumer_key@";
|
public static string ClientId = "@credentials_picasa_consumer_key@";
|
||||||
public static string ConsumerSecret = "@credentials_picasa_consumer_secret@";
|
public static string ClientSecret = "@credentials_picasa_consumer_secret@";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,25 +17,25 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.IniFile;
|
||||||
using Greenshot.Plugin;
|
using Greenshot.Plugin;
|
||||||
using GreenshotPlugin.Core;
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
namespace GreenshotPicasaPlugin {
|
namespace GreenshotPicasaPlugin {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of PicasaUtils.
|
/// Description of PicasaUtils.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PicasaUtils {
|
public static class PicasaUtils {
|
||||||
private const string GoogleAccountUri = "https://www.google.com/accounts/";
|
private const string PicasaScope = "https://picasaweb.google.com/data/";
|
||||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PicasaUtils));
|
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PicasaUtils));
|
||||||
private static readonly PicasaConfiguration Config = IniConfig.GetIniSection<PicasaConfiguration>();
|
private static readonly PicasaConfiguration Config = IniConfig.GetIniSection<PicasaConfiguration>();
|
||||||
|
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 PicasaUtils() {
|
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>
|
/// <summary>
|
||||||
/// Do the actual upload to Picasa
|
/// Do the actual upload to Picasa
|
||||||
|
@ -46,46 +46,46 @@ namespace GreenshotPicasaPlugin {
|
||||||
/// <param name="filename"></param>
|
/// <param name="filename"></param>
|
||||||
/// <returns>PicasaResponse</returns>
|
/// <returns>PicasaResponse</returns>
|
||||||
public static string UploadToPicasa(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
|
public static string UploadToPicasa(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
|
||||||
OAuthSession oAuth = new OAuthSession(PicasaCredentials.ConsumerKey, PicasaCredentials.ConsumerSecret);
|
// Fill the OAuth2Settings
|
||||||
oAuth.BrowserSize = new Size(1020, 590);
|
OAuth2Settings settings = new OAuth2Settings();
|
||||||
oAuth.AccessTokenUrl = GoogleAccountUri + "OAuthGetAccessToken";
|
settings.AuthUrlPattern = AuthUrl;
|
||||||
oAuth.AuthorizeUrl = GoogleAccountUri + "OAuthAuthorizeToken";
|
settings.TokenUrl = TokenUrl;
|
||||||
oAuth.RequestTokenUrl = GoogleAccountUri + "OAuthGetRequestToken";
|
settings.CloudServiceName = "Picasa";
|
||||||
oAuth.LoginTitle = "Picasa authorization";
|
settings.ClientId = PicasaCredentials.ClientId;
|
||||||
oAuth.Token = Config.PicasaToken;
|
settings.ClientSecret = PicasaCredentials.ClientSecret;
|
||||||
oAuth.TokenSecret = Config.PicasaTokenSecret;
|
settings.AuthorizeMode = OAuth2AuthorizeMode.LocalServer;
|
||||||
oAuth.RequestTokenParameters.Add("scope", "https://picasaweb.google.com/data/");
|
|
||||||
oAuth.RequestTokenParameters.Add("xoauth_displayname", "Greenshot");
|
// Copy the settings from the config, which is kept in memory and on the disk
|
||||||
if (string.IsNullOrEmpty(oAuth.Token)) {
|
settings.RefreshToken = Config.RefreshToken;
|
||||||
if (!oAuth.Authorize()) {
|
settings.AccessToken = Config.AccessToken;
|
||||||
return null;
|
settings.AccessTokenExpires = Config.AccessTokenExpires;
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(oAuth.Token)) {
|
|
||||||
Config.PicasaToken = oAuth.Token;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
|
|
||||||
Config.PicasaTokenSecret = oAuth.TokenSecret;
|
|
||||||
}
|
|
||||||
IniConfig.Save();
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
IDictionary<string, string> headers = new Dictionary<string, string>();
|
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings);
|
||||||
headers.Add("slug", OAuthSession.UrlEncode3986(filename));
|
if (Config.AddFilename) {
|
||||||
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));
|
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);
|
return ParseResponse(response);
|
||||||
} catch (Exception ex) {
|
|
||||||
LOG.Error("Upload error: ", ex);
|
|
||||||
throw;
|
|
||||||
} finally {
|
} finally {
|
||||||
if (!string.IsNullOrEmpty(oAuth.Token)) {
|
// Copy the settings back to the config, so they are stored.
|
||||||
Config.PicasaToken = oAuth.Token;
|
Config.RefreshToken = settings.RefreshToken;
|
||||||
}
|
Config.AccessToken = settings.AccessToken;
|
||||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
|
Config.AccessTokenExpires = settings.AccessTokenExpires;
|
||||||
Config.PicasaTokenSecret = oAuth.TokenSecret;
|
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) {
|
public static string ParseResponse(string response) {
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -18,17 +18,20 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using GreenshotPlugin.Core;
|
using GreenshotPlugin.Core;
|
||||||
using GreenshotPlugin.UnmanagedHelpers;
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
using Greenshot.IniFile;
|
using Greenshot.IniFile;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
namespace GreenshotPlugin.Controls {
|
namespace GreenshotPlugin.Controls {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extend this Form to have the possibility for animations on your form
|
/// Extend this Form to have the possibility for animations on your form
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AnimatingForm : GreenshotForm {
|
public class AnimatingForm : GreenshotForm {
|
||||||
|
private static readonly ILog LOG = LogManager.GetLogger(typeof(AnimatingForm));
|
||||||
private const int DEFAULT_VREFRESH = 60;
|
private const int DEFAULT_VREFRESH = 60;
|
||||||
private int vRefresh = 0;
|
private int vRefresh = 0;
|
||||||
private Timer timer = null;
|
private Timer timer = null;
|
||||||
|
@ -110,7 +113,11 @@ namespace GreenshotPlugin.Controls {
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
void timer_Tick(object sender, EventArgs e) {
|
void timer_Tick(object sender, EventArgs e) {
|
||||||
Animate();
|
try {
|
||||||
|
Animate();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOG.Warn("An exception occured while animating:", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -38,11 +38,11 @@ namespace GreenshotPlugin.Controls {
|
||||||
protected static CoreConfiguration coreConfiguration;
|
protected static CoreConfiguration coreConfiguration;
|
||||||
private static IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
|
private static IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
|
||||||
private IComponentChangeService m_changeService;
|
private IComponentChangeService m_changeService;
|
||||||
private bool isDesignModeLanguageSet = false;
|
private bool _isDesignModeLanguageSet = false;
|
||||||
private bool applyLanguageManually = false;
|
private bool _applyLanguageManually = false;
|
||||||
private bool storeFieldsManually = false;
|
private bool _storeFieldsManually = false;
|
||||||
private IDictionary<string, Control> designTimeControls;
|
private IDictionary<string, Control> _designTimeControls;
|
||||||
private IDictionary<string, ToolStripItem> designTimeToolStripItems;
|
private IDictionary<string, ToolStripItem> _designTimeToolStripItems;
|
||||||
|
|
||||||
static GreenshotForm() {
|
static GreenshotForm() {
|
||||||
if (!IsInDesignMode) {
|
if (!IsInDesignMode) {
|
||||||
|
@ -68,29 +68,37 @@ namespace GreenshotPlugin.Controls {
|
||||||
|
|
||||||
protected bool ManualLanguageApply {
|
protected bool ManualLanguageApply {
|
||||||
get {
|
get {
|
||||||
return applyLanguageManually;
|
return _applyLanguageManually;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
applyLanguageManually = value;
|
_applyLanguageManually = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool ManualStoreFields {
|
protected bool ManualStoreFields {
|
||||||
get {
|
get {
|
||||||
return storeFieldsManually;
|
return _storeFieldsManually;
|
||||||
}
|
}
|
||||||
set {
|
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>
|
/// <summary>
|
||||||
/// Code to initialize the language etc during design time
|
/// Code to initialize the language etc during design time
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void InitializeForDesigner() {
|
protected void InitializeForDesigner() {
|
||||||
if (DesignMode) {
|
if (DesignMode) {
|
||||||
designTimeControls = new Dictionary<string, Control>();
|
_designTimeControls = new Dictionary<string, Control>();
|
||||||
designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
|
_designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
|
||||||
try {
|
try {
|
||||||
ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
|
ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
|
||||||
|
|
||||||
|
@ -119,8 +127,8 @@ namespace GreenshotPlugin.Controls {
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
protected override void OnPaint(PaintEventArgs e) {
|
protected override void OnPaint(PaintEventArgs e) {
|
||||||
if (DesignMode) {
|
if (DesignMode) {
|
||||||
if (!isDesignModeLanguageSet) {
|
if (!_isDesignModeLanguageSet) {
|
||||||
isDesignModeLanguageSet = true;
|
_isDesignModeLanguageSet = true;
|
||||||
try {
|
try {
|
||||||
ApplyLanguage();
|
ApplyLanguage();
|
||||||
} catch (Exception) {
|
} catch (Exception) {
|
||||||
|
@ -131,8 +139,11 @@ namespace GreenshotPlugin.Controls {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLoad(EventArgs e) {
|
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 (!DesignMode) {
|
||||||
if (!applyLanguageManually) {
|
if (!_applyLanguageManually) {
|
||||||
ApplyLanguage();
|
ApplyLanguage();
|
||||||
}
|
}
|
||||||
FillFields();
|
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>
|
/// <summary>
|
||||||
/// check if the form was closed with an OK, if so store the values in the GreenshotControls
|
/// check if the form was closed with an OK, if so store the values in the GreenshotControls
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
protected override void OnClosed(EventArgs e) {
|
protected override void OnClosed(EventArgs e) {
|
||||||
if (!DesignMode && !storeFieldsManually) {
|
if (!DesignMode && !_storeFieldsManually) {
|
||||||
if (DialogResult == DialogResult.OK) {
|
if (DialogResult == DialogResult.OK) {
|
||||||
LOG.Info("Form was closed with OK: storing field values.");
|
LOG.Info("Form was closed with OK: storing field values.");
|
||||||
StoreFields();
|
StoreFields();
|
||||||
|
@ -230,17 +252,17 @@ namespace GreenshotPlugin.Controls {
|
||||||
if (ce.Component != null && ((IComponent)ce.Component).Site != null) {
|
if (ce.Component != null && ((IComponent)ce.Component).Site != null) {
|
||||||
Control control = ce.Component as Control;
|
Control control = ce.Component as Control;
|
||||||
if (control != null) {
|
if (control != null) {
|
||||||
if (!designTimeControls.ContainsKey(control.Name)) {
|
if (!_designTimeControls.ContainsKey(control.Name)) {
|
||||||
designTimeControls.Add(control.Name, control);
|
_designTimeControls.Add(control.Name, control);
|
||||||
} else {
|
} else {
|
||||||
designTimeControls[control.Name] = control;
|
_designTimeControls[control.Name] = control;
|
||||||
}
|
}
|
||||||
} else if (ce.Component is ToolStripItem) {
|
} else if (ce.Component is ToolStripItem) {
|
||||||
ToolStripItem item = ce.Component as ToolStripItem;
|
ToolStripItem item = ce.Component as ToolStripItem;
|
||||||
if (!designTimeControls.ContainsKey(item.Name)) {
|
if (!_designTimeControls.ContainsKey(item.Name)) {
|
||||||
designTimeToolStripItems.Add(item.Name, item);
|
_designTimeToolStripItems.Add(item.Name, item);
|
||||||
} else {
|
} else {
|
||||||
designTimeToolStripItems[item.Name] = item;
|
_designTimeToolStripItems[item.Name] = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,10 +382,10 @@ namespace GreenshotPlugin.Controls {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DesignMode) {
|
if (DesignMode) {
|
||||||
foreach (Control designControl in designTimeControls.Values) {
|
foreach (Control designControl in _designTimeControls.Values) {
|
||||||
ApplyLanguage(designControl);
|
ApplyLanguage(designControl);
|
||||||
}
|
}
|
||||||
foreach (ToolStripItem designToolStripItem in designTimeToolStripItems.Values) {
|
foreach (ToolStripItem designToolStripItem in _designTimeToolStripItems.Values) {
|
||||||
ApplyLanguage(designToolStripItem);
|
ApplyLanguage(designToolStripItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +435,7 @@ namespace GreenshotPlugin.Controls {
|
||||||
if (section != null) {
|
if (section != null) {
|
||||||
IniValue iniValue = null;
|
IniValue iniValue = null;
|
||||||
if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue)) {
|
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;
|
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.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.addressTextBox = new System.Windows.Forms.TextBox();
|
this._addressTextBox = new System.Windows.Forms.TextBox();
|
||||||
this.browser = new ExtendedWebBrowser();
|
this._browser = new ExtendedWebBrowser();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// addressTextBox
|
// _addressTextBox
|
||||||
//
|
//
|
||||||
this.addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
|
this._addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
|
||||||
this.addressTextBox.Dock = System.Windows.Forms.DockStyle.Top;
|
this._addressTextBox.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
this.addressTextBox.Enabled = false;
|
this._addressTextBox.Enabled = false;
|
||||||
this.addressTextBox.Location = new System.Drawing.Point(0, 0);
|
this._addressTextBox.Location = new System.Drawing.Point(0, 0);
|
||||||
this.addressTextBox.Name = "addressTextBox";
|
this._addressTextBox.Name = "addressTextBox";
|
||||||
this.addressTextBox.Size = new System.Drawing.Size(595, 20);
|
this._addressTextBox.Size = new System.Drawing.Size(595, 20);
|
||||||
this.addressTextBox.TabIndex = 3;
|
this._addressTextBox.TabIndex = 3;
|
||||||
this.addressTextBox.TabStop = false;
|
this._addressTextBox.TabStop = false;
|
||||||
//
|
//
|
||||||
// browser
|
// _browser
|
||||||
//
|
//
|
||||||
this.browser.Dock = System.Windows.Forms.DockStyle.Fill;
|
this._browser.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.browser.Location = new System.Drawing.Point(0, 20);
|
this._browser.Location = new System.Drawing.Point(0, 20);
|
||||||
this.browser.MinimumSize = new System.Drawing.Size(100, 100);
|
this._browser.MinimumSize = new System.Drawing.Size(100, 100);
|
||||||
this.browser.Name = "browser";
|
this._browser.Name = "browser";
|
||||||
this.browser.Size = new System.Drawing.Size(595, 295);
|
this._browser.Size = new System.Drawing.Size(595, 295);
|
||||||
this.browser.TabIndex = 4;
|
this._browser.TabIndex = 4;
|
||||||
//
|
//
|
||||||
// OAuthLoginForm
|
// OAuthLoginForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(595, 315);
|
this.ClientSize = new System.Drawing.Size(595, 315);
|
||||||
this.Controls.Add(this.browser);
|
this.Controls.Add(this._browser);
|
||||||
this.Controls.Add(this.addressTextBox);
|
this.Controls.Add(this._addressTextBox);
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.MinimizeBox = false;
|
this.MinimizeBox = false;
|
||||||
this.Name = "OAuthLoginForm";
|
this.Name = "OAuthLoginForm";
|
||||||
|
@ -85,8 +85,8 @@ namespace GreenshotPlugin.Controls {
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.TextBox addressTextBox;
|
private System.Windows.Forms.TextBox _addressTextBox;
|
||||||
private ExtendedWebBrowser browser;
|
private ExtendedWebBrowser _browser;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,62 +35,74 @@ namespace GreenshotPlugin.Controls {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class OAuthLoginForm : Form {
|
public partial class OAuthLoginForm : Form {
|
||||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm));
|
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm));
|
||||||
private string callbackUrl = null;
|
private string _callbackUrl = null;
|
||||||
private IDictionary<string, string> callbackParameters = null;
|
private IDictionary<string, string> _callbackParameters = null;
|
||||||
|
|
||||||
public IDictionary<string, string> CallbackParameters {
|
public IDictionary<string, string> CallbackParameters {
|
||||||
get { return callbackParameters; }
|
get {
|
||||||
|
return _callbackParameters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool isOk {
|
public bool IsOk {
|
||||||
get {
|
get {
|
||||||
return DialogResult == DialogResult.OK;
|
return DialogResult == DialogResult.OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) {
|
public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) {
|
||||||
this.callbackUrl = callbackUrl;
|
_callbackUrl = callbackUrl;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ClientSize = size;
|
ClientSize = size;
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
Icon = GreenshotResources.getGreenshotIcon();
|
||||||
Text = browserTitle;
|
Text = browserTitle;
|
||||||
addressTextBox.Text = authorizationLink;
|
_addressTextBox.Text = authorizationLink;
|
||||||
|
|
||||||
// The script errors are suppressed by using the ExtendedWebBrowser
|
// The script errors are suppressed by using the ExtendedWebBrowser
|
||||||
browser.ScriptErrorsSuppressed = false;
|
_browser.ScriptErrorsSuppressed = false;
|
||||||
browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
|
_browser.DocumentCompleted += Browser_DocumentCompleted;
|
||||||
browser.Navigate(new Uri(authorizationLink));
|
_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);
|
WindowDetails.ToForeground(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
|
private void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
|
||||||
LOG.DebugFormat("document completed with url: {0}", browser.Url);
|
LOG.DebugFormat("document completed with url: {0}", _browser.Url);
|
||||||
checkUrl();
|
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_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
|
private void Browser_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
|
||||||
LOG.DebugFormat("Navigated to url: {0}", browser.Url);
|
LOG.DebugFormat("Navigating to url: {0}", _browser.Url);
|
||||||
checkUrl();
|
_addressTextBox.Text = e.Url.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkUrl() {
|
private void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
|
||||||
if (browser.Url.ToString().StartsWith(callbackUrl)) {
|
LOG.DebugFormat("Navigated to url: {0}", _browser.Url);
|
||||||
string queryParams = browser.Url.Query;
|
CheckUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckUrl() {
|
||||||
|
if (_browser.Url.ToString().StartsWith(_callbackUrl)) {
|
||||||
|
string queryParams = _browser.Url.Query;
|
||||||
if (queryParams.Length > 0) {
|
if (queryParams.Length > 0) {
|
||||||
queryParams = NetworkHelper.UrlDecode(queryParams);
|
queryParams = NetworkHelper.UrlDecode(queryParams);
|
||||||
//Store the Token and Token Secret
|
//Store the Token and Token Secret
|
||||||
callbackParameters = NetworkHelper.ParseQueryString(queryParams);
|
_callbackParameters = NetworkHelper.ParseQueryString(queryParams);
|
||||||
}
|
}
|
||||||
DialogResult = DialogResult.OK;
|
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
|
//Cancel the key press so the user can't enter a new url
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,14 +41,13 @@ namespace GreenshotPlugin.Controls {
|
||||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
//
|
//
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Icon = GreenshotResources.getGreenshotIcon();
|
|
||||||
|
|
||||||
checkBox_reduceColors.Checked = Settings.ReduceColors;
|
checkBox_reduceColors.Checked = Settings.ReduceColors;
|
||||||
trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
||||||
trackBarJpegQuality.Value = Settings.JPGQuality;
|
trackBarJpegQuality.Value = Settings.JPGQuality;
|
||||||
textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
||||||
textBoxJpegQuality.Text = Settings.JPGQuality.ToString();
|
textBoxJpegQuality.Text = Settings.JPGQuality.ToString();
|
||||||
WindowDetails.ToForeground(Handle);
|
ToFront = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button_okClick(object sender, EventArgs e) {
|
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;
|
public int WebRequestTimeout;
|
||||||
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
||||||
public int WebRequestReadWriteTimeout;
|
public int WebRequestReadWriteTimeout;
|
||||||
|
@ -407,6 +407,17 @@ namespace GreenshotPlugin.Core {
|
||||||
return base.PreCheckValue(propertyName, propertyValue);
|
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>
|
/// <summary>
|
||||||
/// This method will be called after reading the configuration, so eventually some corrections can be made
|
/// This method will be called after reading the configuration, so eventually some corrections can be made
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -498,8 +509,8 @@ namespace GreenshotPlugin.Core {
|
||||||
OutputFileReduceColorsTo = 256;
|
OutputFileReduceColorsTo = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebRequestTimeout < 1) {
|
if (WebRequestTimeout <= 10) {
|
||||||
WebRequestTimeout = 10;
|
WebRequestTimeout = 100;
|
||||||
}
|
}
|
||||||
if (WebRequestReadWriteTimeout < 1) {
|
if (WebRequestReadWriteTimeout < 1) {
|
||||||
WebRequestReadWriteTimeout = 100;
|
WebRequestReadWriteTimeout = 100;
|
||||||
|
|
|
@ -33,6 +33,17 @@ using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace GreenshotPlugin.Core {
|
namespace GreenshotPlugin.Core {
|
||||||
|
/// <summary>
|
||||||
|
/// HTTP Method to make sure we have the correct method
|
||||||
|
/// </summary>
|
||||||
|
public enum HTTPMethod {
|
||||||
|
GET,
|
||||||
|
POST,
|
||||||
|
PUT,
|
||||||
|
DELETE,
|
||||||
|
HEAD
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of NetworkHelper.
|
/// Description of NetworkHelper.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -54,11 +65,7 @@ namespace GreenshotPlugin.Core {
|
||||||
/// <param name="uri">An Uri to specify the download location</param>
|
/// <param name="uri">An Uri to specify the download location</param>
|
||||||
/// <returns>string with the file content</returns>
|
/// <returns>string with the file content</returns>
|
||||||
public static string GetAsString(Uri uri) {
|
public static string GetAsString(Uri uri) {
|
||||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
return GetResponseAsString(CreateWebRequest(uri));
|
||||||
webRequest.Method = "GET";
|
|
||||||
webRequest.KeepAlive = true;
|
|
||||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
|
||||||
return GetResponse(webRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -86,6 +93,26 @@ namespace GreenshotPlugin.Core {
|
||||||
return null;
|
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>
|
/// <summary>
|
||||||
/// Download the uri to Bitmap
|
/// Download the uri to Bitmap
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -93,15 +120,27 @@ namespace GreenshotPlugin.Core {
|
||||||
/// <returns>Bitmap</returns>
|
/// <returns>Bitmap</returns>
|
||||||
public static Image DownloadImage(string url) {
|
public static Image DownloadImage(string url) {
|
||||||
try {
|
try {
|
||||||
HttpWebRequest request = CreateWebRequest(url);
|
string content;
|
||||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
using (MemoryStream memoryStream = GetAsMemoryStream(url)) {
|
||||||
if (request.HaveResponse) {
|
try {
|
||||||
using (Stream responseStream = response.GetResponseStream()) {
|
using (Image image = Image.FromStream(memoryStream)) {
|
||||||
if (responseStream != null) {
|
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||||
using (Image image = Image.FromStream(responseStream)) {
|
}
|
||||||
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) {
|
} catch (Exception e) {
|
||||||
|
@ -111,14 +150,36 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="uri">string with uri to connect to</param>
|
/// <param name="uri">string with uri to connect to</param>
|
||||||
/// <returns>WebRequest</returns>
|
/// <returns>WebRequest</returns>
|
||||||
public static HttpWebRequest CreateWebRequest(string uri) {
|
public static HttpWebRequest CreateWebRequest(string uri) {
|
||||||
return CreateWebRequest(new Uri(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>
|
/// <summary>
|
||||||
/// Helper method to create a web request, eventually with proxy
|
/// Helper method to create a web request, eventually with proxy
|
||||||
/// </summary>
|
/// </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
|
// BUG-1655: Fix that Greenshot always uses the default proxy even if the "use default proxy" checkbox is unset
|
||||||
webRequest.Proxy = null;
|
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;
|
webRequest.AllowAutoRedirect = true;
|
||||||
// Set default timeouts
|
// Set default timeouts
|
||||||
webRequest.Timeout = Config.WebRequestTimeout*1000;
|
webRequest.Timeout = Config.WebRequestTimeout*1000;
|
||||||
|
@ -320,19 +385,57 @@ namespace GreenshotPlugin.Core {
|
||||||
string footer = "\r\n--" + boundary + "--\r\n";
|
string footer = "\r\n--" + boundary + "--\r\n";
|
||||||
formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
|
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>
|
/// <summary>
|
||||||
/// Process the web response.
|
/// Process the web response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="webRequest">The request object.</param>
|
/// <param name="webRequest">The request object.</param>
|
||||||
/// <returns>The response data.</returns>
|
/// <returns>The response data.</returns>
|
||||||
/// TODO: This method should handle the StatusCode better!
|
/// 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;
|
string responseData = null;
|
||||||
try {
|
try {
|
||||||
HttpWebResponse response = (HttpWebResponse) webRequest.GetResponse();
|
HttpWebResponse response = (HttpWebResponse) webRequest.GetResponse();
|
||||||
LOG.InfoFormat("Response status: {0}", response.StatusCode);
|
LOG.InfoFormat("Response status: {0}", response.StatusCode);
|
||||||
bool isHttpError = (int) response.StatusCode >= 300;
|
bool isHttpError = (int) response.StatusCode >= 300;
|
||||||
|
DebugHeaders(response);
|
||||||
Stream responseStream = response.GetResponseStream();
|
Stream responseStream = response.GetResponseStream();
|
||||||
if (responseStream != null) {
|
if (responseStream != null) {
|
||||||
using (StreamReader reader = new StreamReader(responseStream, true)) {
|
using (StreamReader reader = new StreamReader(responseStream, true)) {
|
||||||
|
@ -348,7 +451,13 @@ namespace GreenshotPlugin.Core {
|
||||||
LOG.ErrorFormat("HTTP error {0}", response.StatusCode);
|
LOG.ErrorFormat("HTTP error {0}", response.StatusCode);
|
||||||
using (Stream responseStream = response.GetResponseStream()) {
|
using (Stream responseStream = response.GetResponseStream()) {
|
||||||
if (responseStream != null) {
|
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) {
|
public static DateTime GetLastModified(Uri uri) {
|
||||||
try {
|
try {
|
||||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||||
webRequest.Method = "HEAD";
|
webRequest.Method = HTTPMethod.HEAD.ToString();
|
||||||
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||||
LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
|
LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
|
||||||
return webResponse.LastModified;
|
return webResponse.LastModified;
|
||||||
|
|
|
@ -19,30 +19,198 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using log4net;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using GreenshotPlugin.Controls;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using log4net;
|
|
||||||
|
|
||||||
namespace GreenshotPlugin.Core {
|
namespace GreenshotPlugin.Core {
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public enum OAuthSignatureTypes {
|
public enum OAuthSignatureTypes {
|
||||||
HMACSHA1,
|
HMACSHA1,
|
||||||
PLAINTEXT,
|
PLAINTEXT,
|
||||||
RSASHA1
|
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 {
|
public class OAuthSession {
|
||||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthSession));
|
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthSession));
|
||||||
protected const string OAUTH_VERSION = "1.0";
|
protected const string OAUTH_VERSION = "1.0";
|
||||||
|
@ -102,7 +270,7 @@ namespace GreenshotPlugin.Core {
|
||||||
private readonly string _consumerKey;
|
private readonly string _consumerKey;
|
||||||
private readonly string _consumerSecret;
|
private readonly string _consumerSecret;
|
||||||
|
|
||||||
// default browser size
|
// default _browser size
|
||||||
private Size _browserSize = new Size(864, 587);
|
private Size _browserSize = new Size(864, 587);
|
||||||
private string _loginTitle = "Authorize Greenshot access";
|
private string _loginTitle = "Authorize Greenshot access";
|
||||||
|
|
||||||
|
@ -339,7 +507,7 @@ namespace GreenshotPlugin.Core {
|
||||||
LOG.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink);
|
LOG.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink);
|
||||||
OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(LoginTitle, BrowserSize, AuthorizationLink, CallbackUrl);
|
OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(LoginTitle, BrowserSize, AuthorizationLink, CallbackUrl);
|
||||||
oAuthLoginForm.ShowDialog();
|
oAuthLoginForm.ShowDialog();
|
||||||
if (oAuthLoginForm.isOk) {
|
if (oAuthLoginForm.IsOk) {
|
||||||
if (oAuthLoginForm.CallbackParameters != null) {
|
if (oAuthLoginForm.CallbackParameters != null) {
|
||||||
string tokenValue;
|
string tokenValue;
|
||||||
if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_TOKEN_KEY, out tokenValue)) {
|
if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_TOKEN_KEY, out tokenValue)) {
|
||||||
|
@ -672,11 +840,9 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create webrequest
|
// Create webrequest
|
||||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestURL);
|
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestURL, method);
|
||||||
webRequest.Method = method.ToString();
|
|
||||||
webRequest.ServicePoint.Expect100Continue = false;
|
webRequest.ServicePoint.Expect100Continue = false;
|
||||||
webRequest.UserAgent = _userAgent;
|
webRequest.UserAgent = _userAgent;
|
||||||
webRequest.Timeout = 100000;
|
|
||||||
|
|
||||||
if (UseHTTPHeadersForAuthorization && authHeader != null) {
|
if (UseHTTPHeadersForAuthorization && authHeader != null) {
|
||||||
LOG.DebugFormat("Authorization: OAuth {0}", authHeader);
|
LOG.DebugFormat("Authorization: OAuth {0}", authHeader);
|
||||||
|
@ -720,7 +886,7 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
string responseData;
|
string responseData;
|
||||||
try {
|
try {
|
||||||
responseData = NetworkHelper.GetResponse(webRequest);
|
responseData = NetworkHelper.GetResponseAsString(webRequest);
|
||||||
LOG.DebugFormat("Response: {0}", responseData);
|
LOG.DebugFormat("Response: {0}", responseData);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.Error("Couldn't retrieve response: ", ex);
|
LOG.Error("Couldn't retrieve response: ", ex);
|
||||||
|
@ -732,4 +898,417 @@ namespace GreenshotPlugin.Core {
|
||||||
return responseData;
|
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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -28,39 +29,39 @@ using log4net;
|
||||||
|
|
||||||
namespace GreenshotPlugin.Core {
|
namespace GreenshotPlugin.Core {
|
||||||
public class SourceforgeFile {
|
public class SourceforgeFile {
|
||||||
private string file;
|
private readonly string _file;
|
||||||
public string File {
|
public string File {
|
||||||
get {return file;}
|
get {return _file;}
|
||||||
}
|
}
|
||||||
private DateTime pubdate;
|
private readonly DateTime _pubdate;
|
||||||
public DateTime Pubdate {
|
public DateTime Pubdate {
|
||||||
get {return pubdate;}
|
get {return _pubdate;}
|
||||||
}
|
}
|
||||||
private string link;
|
private readonly string _link;
|
||||||
public string Link {
|
public string Link {
|
||||||
get {return link;}
|
get {return _link;}
|
||||||
}
|
}
|
||||||
private string directLink;
|
private readonly string _directLink;
|
||||||
public string DirectLink {
|
public string DirectLink {
|
||||||
get {return directLink;}
|
get {return _directLink;}
|
||||||
}
|
}
|
||||||
private Version version;
|
private Version _version;
|
||||||
public Version Version {
|
public Version Version {
|
||||||
get {return version;}
|
get {return _version;}
|
||||||
set {
|
set {
|
||||||
version = value;
|
_version = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private string language;
|
private string _language;
|
||||||
public string Language {
|
public string Language {
|
||||||
get {return language;}
|
get {return _language;}
|
||||||
set {language = value;}
|
set {_language = value;}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool isExe {
|
public bool isExe {
|
||||||
get {
|
get {
|
||||||
if (file != null) {
|
if (_file != null) {
|
||||||
return file.ToLower().EndsWith(".exe");
|
return _file.ToLower().EndsWith(".exe");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -68,8 +69,8 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
public bool isUnstable {
|
public bool isUnstable {
|
||||||
get {
|
get {
|
||||||
if (file != null) {
|
if (_file != null) {
|
||||||
return file.ToLower().Contains("unstable");
|
return _file.ToLower().Contains("unstable");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -77,18 +78,18 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
public bool isReleaseCandidate {
|
public bool isReleaseCandidate {
|
||||||
get {
|
get {
|
||||||
if (file != null) {
|
if (_file != null) {
|
||||||
return Regex.IsMatch(file.ToLower(), "rc[0-9]+");
|
return Regex.IsMatch(_file.ToLower(), "rc[0-9]+");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceforgeFile(string file, string pubdate, string link, string directLink) {
|
public SourceforgeFile(string file, string pubdate, string link, string directLink) {
|
||||||
this.file = file;
|
this._file = file;
|
||||||
this.pubdate = DateTime.Parse(pubdate);
|
DateTime.TryParse(pubdate, out _pubdate);
|
||||||
this.link = link;
|
this._link = link;
|
||||||
this.directLink = directLink;
|
this._directLink = directLink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -113,10 +114,9 @@ namespace GreenshotPlugin.Core {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Dictionary<string, Dictionary<string, RssFile>> with files and their RssFile "description"</returns>
|
/// <returns>Dictionary<string, Dictionary<string, RssFile>> with files and their RssFile "description"</returns>
|
||||||
public static Dictionary<string, Dictionary<string, SourceforgeFile>> readRSS() {
|
public static Dictionary<string, Dictionary<string, SourceforgeFile>> readRSS() {
|
||||||
HttpWebRequest webRequest;
|
|
||||||
XmlDocument rssDoc = new XmlDocument();
|
XmlDocument rssDoc = new XmlDocument();
|
||||||
try {
|
try {
|
||||||
webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(RSSFEED);
|
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(RSSFEED);
|
||||||
XmlTextReader rssReader = new XmlTextReader(webRequest.GetResponse().GetResponseStream());
|
XmlTextReader rssReader = new XmlTextReader(webRequest.GetResponse().GetResponseStream());
|
||||||
|
|
||||||
// Load the XML content into a XmlDocument
|
// Load the XML content into a XmlDocument
|
||||||
|
|
|
@ -1,90 +1,166 @@
|
||||||
/*
|
/*
|
||||||
* Greenshot - a free and open source screenshot tool
|
* Greenshot - a free and open source screenshot tool
|
||||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
*
|
*
|
||||||
* For more information see: http://getgreenshot.org/
|
* For more information see: http://getgreenshot.org/
|
||||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 1 of the License, or
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Security.Cryptography;
|
||||||
using log4net;
|
using System.Text;
|
||||||
|
using log4net;
|
||||||
namespace GreenshotPlugin.Core {
|
using System.Text.RegularExpressions;
|
||||||
public static class EncryptionHelper {
|
using System.Collections.Generic;
|
||||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(EncryptionHelper));
|
using System.Reflection;
|
||||||
private const string RGBIV = "dlgjowejgogkklwj";
|
|
||||||
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
|
namespace GreenshotPlugin.Core {
|
||||||
|
public static class StringExtensions {
|
||||||
/// <summary>
|
private static readonly ILog LOG = LogManager.GetLogger(typeof(StringExtensions));
|
||||||
/// A simply rijndael aes encryption, can be used to store passwords
|
private const string RGBIV = "dlgjowejgogkklwj";
|
||||||
/// </summary>
|
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
|
||||||
/// <param name="ClearText">the string to call upon</param>
|
|
||||||
/// <returns>an encryped string in base64 form</returns>
|
/// <summary>
|
||||||
public static string Encrypt(this string ClearText) {
|
/// Format a string with the specified object
|
||||||
string returnValue = ClearText;
|
/// </summary>
|
||||||
try {
|
/// <param name="format">String with formatting, like {name}</param>
|
||||||
byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText);
|
/// <param name="source">Object used for the formatting</param>
|
||||||
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
/// <returns>Formatted string</returns>
|
||||||
|
public static string FormatWith(this string format, object source) {
|
||||||
using (MemoryStream ms = new MemoryStream()) {
|
return FormatWith(format, null, source);
|
||||||
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
}
|
||||||
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
|
||||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write)) {
|
/// <summary>
|
||||||
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
|
/// Format the string "format" with the source
|
||||||
cs.FlushFinalBlock();
|
/// </summary>
|
||||||
|
/// <param name="format"></param>
|
||||||
returnValue = Convert.ToBase64String(ms.ToArray());
|
/// <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>
|
||||||
} catch (Exception ex) {
|
public static string FormatWith(this string format, IFormatProvider provider, object source) {
|
||||||
LOG.ErrorFormat("Error encrypting, error: ", ex.Message);
|
if (format == null) {
|
||||||
}
|
throw new ArgumentNullException("format");
|
||||||
return returnValue;
|
}
|
||||||
}
|
|
||||||
|
IDictionary<string, object> properties = new Dictionary<string, object>();
|
||||||
/// <summary>
|
foreach(var propertyInfo in source.GetType().GetProperties()) {
|
||||||
/// A simply rijndael aes decryption, can be used to store passwords
|
if (propertyInfo.CanRead && propertyInfo.CanWrite) {
|
||||||
/// </summary>
|
object value = propertyInfo.GetValue(source, null);
|
||||||
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
|
if (propertyInfo.PropertyType != typeof(IDictionary<string, string>)) {
|
||||||
/// <returns>Decrypeted text</returns>
|
properties.Add(propertyInfo.Name, value);
|
||||||
public static string Decrypt(this string EncryptedText) {
|
} else {
|
||||||
string returnValue = EncryptedText;
|
IDictionary<string, string> dictionary = (IDictionary<string, string>)value;
|
||||||
try {
|
foreach (var propertyKey in dictionary.Keys) {
|
||||||
byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);
|
properties.Add(propertyKey, dictionary[propertyKey]);
|
||||||
using (MemoryStream ms = new MemoryStream()) {
|
}
|
||||||
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
|
||||||
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write)) {
|
List<object> values = new List<object>();
|
||||||
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
|
string rewrittenFormat = r.Replace(format, delegate(Match m) {
|
||||||
cs.FlushFinalBlock();
|
Group startGroup = m.Groups["start"];
|
||||||
returnValue = Encoding.ASCII.GetString(ms.ToArray());
|
Group propertyGroup = m.Groups["property"];
|
||||||
}
|
Group formatGroup = m.Groups["format"];
|
||||||
|
Group endGroup = m.Groups["end"];
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
object value;
|
||||||
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
|
if (properties.TryGetValue(propertyGroup.Value, out value)) {
|
||||||
}
|
values.Add(value);
|
||||||
|
} else {
|
||||||
return returnValue;
|
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\CaptureHandler.cs" />
|
||||||
<Compile Include="Core\EventDelay.cs" />
|
<Compile Include="Core\EventDelay.cs" />
|
||||||
<Compile Include="Core\FastBitmap.cs" />
|
<Compile Include="Core\FastBitmap.cs" />
|
||||||
|
<Compile Include="Core\WmInputLangChangeRequestFilter.cs" />
|
||||||
<Compile Include="GlobalSuppressions.cs" />
|
<Compile Include="GlobalSuppressions.cs" />
|
||||||
<Compile Include="IEInterop\IHTMLBodyElement.cs" />
|
<Compile Include="IEInterop\IHTMLBodyElement.cs" />
|
||||||
<Compile Include="IEInterop\IHTMLCurrentStyle.cs" />
|
<Compile Include="IEInterop\IHTMLCurrentStyle.cs" />
|
||||||
|
@ -155,7 +156,7 @@
|
||||||
<Compile Include="Core\CoreConfiguration.cs" />
|
<Compile Include="Core\CoreConfiguration.cs" />
|
||||||
<Compile Include="Core\CredentialsHelper.cs" />
|
<Compile Include="Core\CredentialsHelper.cs" />
|
||||||
<Compile Include="Core\Effects.cs" />
|
<Compile Include="Core\Effects.cs" />
|
||||||
<Compile Include="Core\EncryptionHelper.cs" />
|
<Compile Include="Core\StringExtensions.cs" />
|
||||||
<Compile Include="Core\FilenameHelper.cs" />
|
<Compile Include="Core\FilenameHelper.cs" />
|
||||||
<Compile Include="Core\ImageOutput.cs" />
|
<Compile Include="Core\ImageOutput.cs" />
|
||||||
<Compile Include="Core\InterfaceUtils.cs" />
|
<Compile Include="Core\InterfaceUtils.cs" />
|
||||||
|
|
|
@ -58,7 +58,10 @@ namespace Greenshot.IniFile {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flag to specify if values have been changed
|
/// Flag to specify if values have been changed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDirty = false;
|
public bool IsDirty {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supply values we can't put as defaults
|
/// 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:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- 1.2
|
||||||
|
skip_tags: true
|
||||||
configuration: Release
|
configuration: Release
|
||||||
platform: Any CPU
|
platform: Any CPU
|
||||||
|
clone_depth: 1
|
||||||
assembly_info:
|
assembly_info:
|
||||||
patch: true
|
patch: true
|
||||||
file: '**\AssemblyInfo.*'
|
file: '**\AssemblyInfo.*'
|
||||||
|
@ -11,32 +13,40 @@ assembly_info:
|
||||||
assembly_file_version: '{version}'
|
assembly_file_version: '{version}'
|
||||||
assembly_informational_version: '{version}-$(build_type)-$(APPVEYOR_REPO_COMMIT)'
|
assembly_informational_version: '{version}-$(build_type)-$(APPVEYOR_REPO_COMMIT)'
|
||||||
environment:
|
environment:
|
||||||
credentials_box_client_id: key
|
credentials_box_client_id:
|
||||||
credentials_box_client_secret: secret
|
secure: 8MKxTOowo2fat6cNXGbFfvn6typiEtmCKsrptrWiEFUEoKlT1DUn40iGNcIELRA1
|
||||||
credentials_dropbox_consumer_key: key
|
credentials_box_client_secret:
|
||||||
credentials_dropbox_consumer_secret: secret
|
secure: hJhzDVJuGd/WMnoSXhosvOM/1PGcYlKbtQjA6xyrmnmZcqCTMzqIdA6JXlo/V2Br
|
||||||
credentials_flickr_consumer_key: key
|
credentials_dropbox_consumer_key:
|
||||||
credentials_flickr_consumer_secret: secret
|
secure: Da/6KY1cu9CUM3iOqSpcUw==
|
||||||
credentials_imgur_consumer_key: key
|
credentials_dropbox_consumer_secret:
|
||||||
credentials_imgur_consumer_secret: secret
|
secure: KkyKyUY+buT/MZagXDP4cw==
|
||||||
credentials_photobucket_consumer_key: key
|
credentials_flickr_consumer_key:
|
||||||
credentials_photobucket_consumer_secret: secret
|
secure: fY8s0OkOMYwCjSZoL/6yZcP8xeT6J2EJLjbUMI5lAW42S5QT2U2B41KrmeP2NpnQ
|
||||||
credentials_picasa_consumer_key: key
|
credentials_flickr_consumer_secret:
|
||||||
credentials_picasa_consumer_secret: secret
|
secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw=
|
||||||
sourceforge_host: frs.sourceforge.net
|
credentials_imgur_consumer_key:
|
||||||
sourceforge_user: user
|
secure: z8S4QZ3/InPe3dgCf0CNyS0VGKuRyjjP8WMAq+AkK5OZJxZcbIxwobjgelE5CWYL
|
||||||
sourceforge_password: password
|
credentials_imgur_consumer_secret:
|
||||||
sourceforge_hostkey: ssh-rsa 2048 b0:a8:eb:30:ce:1a:0e:6a:4d:7a:6b:3a:0a:c6:27:60
|
secure: ovfXJRorkkKUzbMXuZ4m0U6KF4icngmS+nzSljXJGSKfhI+GNXbMNa//mKYfTCXI
|
||||||
sourceforge_targetpath: /home/frs/project/greenshot/Greenshot/Greenshot 1.3/
|
credentials_photobucket_consumer_key:
|
||||||
build_type: UNSTABLE
|
secure: oo9GD1Y8dkrli6hMfnnYsw==
|
||||||
rsakey: key
|
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:
|
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:
|
build:
|
||||||
project: greenshot\greenshot.sln
|
project: greenshot\greenshot.sln
|
||||||
verbosity: normal
|
verbosity: normal
|
||||||
after_build:
|
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
|
test: off
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: Greenshot\releases\Greenshot*INSTALLER*.exe
|
- path: Greenshot\releases\Greenshot*INSTALLER*.exe
|
||||||
|
@ -49,12 +59,26 @@ artifacts:
|
||||||
name: Readme
|
name: Readme
|
||||||
- path: Greenshot\releases\Greenshot-DEBUGSYMBOLS*.zip
|
- path: Greenshot\releases\Greenshot-DEBUGSYMBOLS*.zip
|
||||||
name: DEBUGSYMBOLS
|
name: DEBUGSYMBOLS
|
||||||
deploy_script:
|
deploy:
|
||||||
- ps: iex (new-object Net.WebClient).DownloadString("https://bitbucket.org/greenshot/greenshot/raw/master/deploy.ps1")
|
- 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:
|
notifications:
|
||||||
- provider: Email
|
- provider: Email
|
||||||
to:
|
to:
|
||||||
- robin@getgreenshot.org
|
- robin@getgreenshot.org
|
||||||
on_build_success: false
|
- jens@getgreenshot.org
|
||||||
on_build_failure: false
|
on_build_success: true
|
||||||
on_build_status_changed: 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