diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs index f76efe454..4fe33f2a6 100644 --- a/GreenshotImgurPlugin/ImgurPlugin.cs +++ b/GreenshotImgurPlugin/ImgurPlugin.cs @@ -157,11 +157,13 @@ namespace GreenshotImgurPlugin { imgurInfo.Image = ImageHelper.CreateThumbnail(image, 90, 90); IniConfig.Save(); - uploadURL = imgurInfo.Page; + uploadURL = null; try { if (config.UsePageLink) { + uploadURL = imgurInfo.Page; Clipboard.SetText(imgurInfo.Page); } else { + uploadURL = imgurInfo.Original; Clipboard.SetText(imgurInfo.Original); } } catch (Exception ex) { diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index 9fe1649c1..7a0740720 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -134,9 +134,7 @@ namespace GreenshotImgurPlugin { uploadRequest.Append(EscapeText(System.Convert.ToBase64String(imageData, 0, dataLength))); // add type uploadRequest.Append("&type=base64"); - // add key - uploadRequest.Append("&key="); - uploadRequest.Append(IMGUR_ANONYMOUS_API_KEY); + // add title if (title != null) { uploadRequest.Append("&title="); @@ -151,6 +149,9 @@ namespace GreenshotImgurPlugin { string responseString; if (config.AnonymousAccess) { + // add key + uploadRequest.Append("&key="); + uploadRequest.Append(IMGUR_ANONYMOUS_API_KEY); url = config.ImgurApiUrl + "/upload"; HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url); @@ -171,10 +172,12 @@ namespace GreenshotImgurPlugin { } else { url = config.ImgurApiUrl + "/account/images"; OAuthHelper oAuth = new OAuthHelper(); + oAuth.BrowserWidth = 650; + oAuth.BrowserHeight = 500; oAuth.CallbackUrl = "http://getgreenshot.org"; - oAuth.AccessTokenUrl = "https://api.imgur.com/oauth/access_token"; - oAuth.AuthorizeUrl = "https://api.imgur.com/oauth/authorize"; - oAuth.RequestTokenUrl = "https://api.imgur.com/oauth/request_token"; + oAuth.AccessTokenUrl = "http://api.imgur.com/oauth/access_token"; + oAuth.AuthorizeUrl = "http://api.imgur.com/oauth/authorize"; + oAuth.RequestTokenUrl = "http://api.imgur.com/oauth/request_token"; oAuth.ConsumerKey = "fill-in"; oAuth.ConsumerSecret = "fill-in"; oAuth.UserAgent = "Greenshot"; @@ -291,31 +294,5 @@ namespace GreenshotImgurPlugin { } catch {} } - - public static void ImgurOAuthExample() { - OAuthHelper oAuth = new OAuthHelper(); - oAuth.CallbackUrl = "http://getgreenshot.org"; - oAuth.AccessTokenUrl = "https://api.imgur.com/oauth/access_token"; - oAuth.AuthorizeUrl = "https://api.imgur.com/oauth/authorize"; - oAuth.RequestTokenUrl = "https://api.imgur.com/oauth/request_token"; - oAuth.ConsumerKey = "907d4455b8c38144d68c4f72190af4c40504a0ac7"; - oAuth.ConsumerSecret = "d33902ef409fea163ab755454c15b3d0"; - oAuth.UserAgent = "Greenshot"; - if (string.IsNullOrEmpty(config.ImgurToken)) { - LOG.Debug("Creating Imgur Token"); - oAuth.getRequestToken(); - if (string.IsNullOrEmpty(oAuth.authorizeToken("Imgur authorization"))) { - return; - } - string accessToken = oAuth.getAccessToken(); - config.ImgurToken = oAuth.Token; - config.ImgurTokenSecret = oAuth.TokenSecret; - } else { - LOG.Debug("Using stored Imgur Token"); - oAuth.Token = config.ImgurToken; - oAuth.TokenSecret = config.ImgurTokenSecret; - } - System.Windows.Forms.MessageBox.Show(oAuth.oAuthWebRequest(OAuthHelper.Method.GET, "http://api.imgur.com/2/account", null)); - } } } diff --git a/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs index 662976f51..fb5920a3a 100644 --- a/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs +++ b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs @@ -32,9 +32,6 @@ namespace GreenshotPhotobucketPlugin { /// [IniSection("Photobucket", Description="Greenshot Photobucket Plugin configuration")] public class PhotobucketConfiguration : IniSection { - [IniProperty("PhotobucketApiUrl", Description = "Url to Photobucket system.", DefaultValue = "http://api.photobucket.com")] - public string PhotobucketApiUrl; - [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] public OutputFormat UploadFormat; [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] diff --git a/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs b/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs index 907be691d..2cd4d9b5c 100644 --- a/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs +++ b/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs @@ -117,22 +117,24 @@ namespace GreenshotPhotobucketPlugin { host.SaveToStream(image, stream, outputSettings); try { string filename = Path.GetFileName(host.GetFilename(config.UploadFormat, captureDetails)); - PhotobucketInfo PhotobucketInfo = null; + PhotobucketInfo photobucketInfo = null; // Run upload in the background new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("photobucket", LangKey.communication_wait), delegate() { - PhotobucketInfo = PhotobucketUtils.UploadToPhotobucket(stream.GetBuffer(), (int)stream.Length, captureDetails.Title, filename); + photobucketInfo = PhotobucketUtils.UploadToPhotobucket(stream.GetBuffer(), (int)stream.Length, captureDetails.Title, filename); } ); + // This causes an exeption if the upload failed :) + LOG.DebugFormat("Uploaded to Photobucket page: " + photobucketInfo.Page); uploadURL = null; try { if (config.UsePageLink) { - uploadURL = PhotobucketInfo.Page; - Clipboard.SetText(PhotobucketInfo.Page); + uploadURL = photobucketInfo.Page; + Clipboard.SetText(photobucketInfo.Page); } else { - uploadURL = PhotobucketInfo.Original; - Clipboard.SetText(PhotobucketInfo.Original); + uploadURL = photobucketInfo.Original; + Clipboard.SetText(photobucketInfo.Original); } } catch (Exception ex) { LOG.Error("Can't write to clipboard: ", ex); diff --git a/GreenshotPhotobucketPlugin/PhotobucketUtils.cs b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs index 16c7d0b8b..26e4c08d8 100644 --- a/GreenshotPhotobucketPlugin/PhotobucketUtils.cs +++ b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs @@ -93,20 +93,30 @@ namespace GreenshotPhotobucketPlugin { uploadRequest.Append("&filename="); uploadRequest.Append(EscapeText(filename)); } - string url = config.PhotobucketApiUrl + "/album/greenshot/upload"; + string url = "http://api.photobucket.com/album/greenshot/upload"; string responseString; OAuthHelper oAuth = new OAuthHelper(); + // This url is configured in the Photobucket API settings in the Photobucket site!! oAuth.CallbackUrl = "http://getgreenshot.org"; oAuth.AccessTokenUrl = "http://api.photobucket.com/login/access"; - oAuth.AuthorizeUrl = " http://photobucket.com/apilogin/login"; + oAuth.AuthorizeUrl = "http://photobucket.com/apilogin/login"; oAuth.RequestTokenUrl = "http://api.photobucket.com/login/request"; oAuth.ConsumerKey = "fill-in"; oAuth.ConsumerSecret = "fill-in"; oAuth.UserAgent = "Greenshot"; + oAuth.BrowserWidth = 1010; + oAuth.BrowserHeight = 400; + oAuth.CheckVerifier = false; if (string.IsNullOrEmpty(config.PhotobucketToken)) { LOG.Debug("Creating Photobucket Token"); - oAuth.getRequestToken(); + try { + oAuth.getRequestToken(); + } catch (Exception ex) { + LOG.Error(ex); + throw new NotSupportedException("Photobucket is not available: " + ex.Message); + } + LOG.Debug("Authorizing Photobucket"); if (string.IsNullOrEmpty(oAuth.authorizeToken("Photobucket authorization"))) { return null; } diff --git a/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs b/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs index 45e4de037..7363fc4ec 100644 --- a/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs +++ b/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs @@ -44,52 +44,49 @@ namespace GreenshotPlugin.Controls { /// the contents of this method with the code editor. /// private void InitializeComponent() { - this.browser = new System.Windows.Forms.WebBrowser(); - this.addressTextBox = new System.Windows.Forms.TextBox(); - this.SuspendLayout(); - // - // browser - // - this.browser.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.browser.Location = new System.Drawing.Point(0, 26); - this.browser.MinimumSize = new System.Drawing.Size(20, 20); - this.browser.Name = "browser"; - this.browser.Size = new System.Drawing.Size(864, 561); - this.browser.TabIndex = 0; - this.browser.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.webBrowser1_Navigating); - this.browser.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.browser_Navigated); - // - // addressTextBox - // - this.addressTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.addressTextBox.Location = new System.Drawing.Point(7, 2); - this.addressTextBox.Name = "addressTextBox"; - this.addressTextBox.Size = new System.Drawing.Size(840, 20); - this.addressTextBox.TabIndex = 1; - this.addressTextBox.TabStop = false; - this.addressTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.addressTextBox_KeyPress); - // - // LoginForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(864, 587); - this.Controls.Add(this.addressTextBox); - this.Controls.Add(this.browser); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "LoginForm"; - this.ShowInTaskbar = false; - this.ResumeLayout(false); - this.PerformLayout(); + this.addressTextBox = new System.Windows.Forms.TextBox(); + this.browser = new System.Windows.Forms.WebBrowser(); + this.SuspendLayout(); + // + // addressTextBox + // + this.addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow; + this.addressTextBox.Dock = System.Windows.Forms.DockStyle.Top; + this.addressTextBox.Enabled = false; + this.addressTextBox.Location = new System.Drawing.Point(0, 0); + this.addressTextBox.Name = "addressTextBox"; + this.addressTextBox.Size = new System.Drawing.Size(595, 20); + this.addressTextBox.TabIndex = 3; + this.addressTextBox.TabStop = false; + // + // browser + // + this.browser.Dock = System.Windows.Forms.DockStyle.Fill; + this.browser.Location = new System.Drawing.Point(0, 20); + this.browser.MinimumSize = new System.Drawing.Size(100, 100); + this.browser.Name = "browser"; + this.browser.Size = new System.Drawing.Size(595, 295); + this.browser.TabIndex = 4; + // + // OAuthLoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(595, 315); + this.Controls.Add(this.browser); + this.Controls.Add(this.addressTextBox); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OAuthLoginForm"; + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion - private System.Windows.Forms.WebBrowser browser; - private System.Windows.Forms.TextBox addressTextBox; + private System.Windows.Forms.TextBox addressTextBox; + private System.Windows.Forms.WebBrowser browser; + } } diff --git a/GreenshotPlugin/Controls/OAuthLoginForm.cs b/GreenshotPlugin/Controls/OAuthLoginForm.cs index 7a7e76297..a4c32cfa2 100644 --- a/GreenshotPlugin/Controls/OAuthLoginForm.cs +++ b/GreenshotPlugin/Controls/OAuthLoginForm.cs @@ -33,6 +33,7 @@ namespace GreenshotPlugin.Controls { /// The OAuthLoginForm is used to allow the user to authorize Greenshot with an "Oauth" application /// public partial class OAuthLoginForm : Form { + private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthLoginForm)); private OAuthHelper _oauth; private String _token; private String _verifier; @@ -56,25 +57,39 @@ namespace GreenshotPlugin.Controls { } } - public OAuthLoginForm(OAuthHelper o, string browserTitle) { + public OAuthLoginForm(OAuthHelper o, string browserTitle, int width, int height) { _oauth = o; _token = null; InitializeComponent(); + this.ClientSize = new System.Drawing.Size(width, height); this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon(); this.Text = browserTitle; this.addressTextBox.Text = o.AuthorizationLink; _token = _oauth.Token; _tokenSecret = _oauth.TokenSecret; + browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted); browser.Navigate(new Uri(_oauth.AuthorizationLink)); + + WindowDetails.ToForeground(this.Handle); } + private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { + LOG.DebugFormat("document completed with url: {0}", browser.Url); + checkUrl(); + } private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) { + LOG.DebugFormat("Navigating to url: {0}", browser.Url); this.addressTextBox.Text = e.Url.ToString(); } private void browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) { - if (browser.Url.ToString().Contains(_oauth.CallbackUrl)) { - string queryParams = e.Url.Query; + LOG.DebugFormat("Navigated to url: {0}", browser.Url); + checkUrl(); + } + + private void checkUrl() { + if (browser.Url.ToString().Contains(_oauth.CallbackUrl)) { + string queryParams = browser.Url.Query; if (queryParams.Length > 0) { //Store the Token and Token Secret NameValueCollection qs = NetworkHelper.ParseQueryString(queryParams); diff --git a/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs b/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs index 2f913a926..1a87c7475 100644 --- a/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs +++ b/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs @@ -91,7 +91,6 @@ namespace GreenshotPlugin.Controls { this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Greenshot"; - this.TopMost = true; this.UseWaitCursor = true; this.ResumeLayout(false); this.PerformLayout(); diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs index 17249c3fb..3f34a63cb 100644 --- a/GreenshotPlugin/Core/NetworkHelper.cs +++ b/GreenshotPlugin/Core/NetworkHelper.cs @@ -26,6 +26,8 @@ using System.Text; using System.Collections.Specialized; using System.Text.RegularExpressions; using Greenshot.IniFile; +using System.Security.Cryptography.X509Certificates; +using System.Net.Security; namespace GreenshotPlugin.Core { /// @@ -35,6 +37,14 @@ namespace GreenshotPlugin.Core { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(NetworkHelper)); private static CoreConfiguration config = IniConfig.GetIniSection(); + static NetworkHelper() { + // Disable certificate checking + System.Net.ServicePointManager.ServerCertificateValidationCallback += + delegate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslError) { + bool validationResult = true; + return validationResult; + }; + } /// /// Download a file as string /// diff --git a/GreenshotPlugin/Core/OAuthHelper.cs b/GreenshotPlugin/Core/OAuthHelper.cs index cc16550d2..baf3ba225 100644 --- a/GreenshotPlugin/Core/OAuthHelper.cs +++ b/GreenshotPlugin/Core/OAuthHelper.cs @@ -30,7 +30,7 @@ using GreenshotPlugin.Controls; namespace GreenshotPlugin.Core { public class OAuthHelper { - + private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthHelper)); /// /// Provides a predefined set of algorithms that are supported officially by the protocol /// @@ -106,6 +106,10 @@ namespace GreenshotPlugin.Core { public enum Method { GET, POST, PUT, DELETE }; private string _userAgent = "Greenshot"; private string _callbackUrl = "http://getgreenshot.org"; + private bool checkVerifier = true; + // default browser size + private int _browserWidth = 864; + private int _browserHeight = 587; #region PublicPropertiies public string ConsumerKey { get; set; } @@ -115,7 +119,35 @@ namespace GreenshotPlugin.Core { public string AuthorizeUrl { get; set; } public string AccessTokenUrl { get; set; } public string CallbackUrl { get { return _callbackUrl;} set { _callbackUrl = value; } } - public string Token { get; set; } + public bool CheckVerifier { + get { + return checkVerifier; + } + set { + checkVerifier = value; + } + } + + public int BrowserWidth { + get { + return _browserWidth; + } + set { + _browserWidth = value; + } + } + public int BrowserHeight { + get { + return _browserHeight; + } + set { + _browserHeight = value; + } + } + public string Token { + get; + set; + } public string TokenSecret { get; set; } #endregion @@ -183,7 +215,7 @@ namespace GreenshotPlugin.Core { /// /// The value to Url encode /// Returns a Url encoded string - public static string UrlEncodeSpecial(string value) { + public static string UrlEncode3986(string value) { StringBuilder result = new StringBuilder(); foreach (char symbol in value) { @@ -260,7 +292,7 @@ namespace GreenshotPlugin.Core { //TODO: Make this less of a hack if (!string.IsNullOrEmpty(callback)) { - parameters.Add(new QueryParameter(OAuthCallbackKey, UrlEncodeSpecial(callback))); + parameters.Add(new QueryParameter(OAuthCallbackKey, UrlEncode3986(callback))); } if (!string.IsNullOrEmpty(token)) { @@ -284,8 +316,8 @@ namespace GreenshotPlugin.Core { StringBuilder signatureBase = new StringBuilder(); signatureBase.AppendFormat("{0}&", httpMethod.ToUpper()); - signatureBase.AppendFormat("{0}&", UrlEncodeSpecial(normalizedUrl)); - signatureBase.AppendFormat("{0}", UrlEncodeSpecial(normalizedRequestParameters)); + signatureBase.AppendFormat("{0}&", UrlEncode3986(normalizedUrl)); + signatureBase.AppendFormat("{0}", UrlEncode3986(normalizedRequestParameters)); return signatureBase.ToString(); } @@ -335,7 +367,7 @@ namespace GreenshotPlugin.Core { case SignatureTypes.HMACSHA1: string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, callback, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters); HMACSHA1 hmacsha1 = new HMACSHA1(); - hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncodeSpecial(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncodeSpecial(tokenSecret))); + hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode3986(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode3986(tokenSecret))); return GenerateSignatureUsingHash(signatureBase, hmacsha1); case SignatureTypes.RSASHA1: @@ -356,15 +388,6 @@ namespace GreenshotPlugin.Core { return Convert.ToInt64(ts.TotalSeconds).ToString(); } - /* - public virtual string GenerateTimeStamp() { - // Default implementation of UNIX time of the current UTC time - TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); - string timeStamp = ts.TotalSeconds.ToString(); - timeStamp = timeStamp.Substring(0, timeStamp.IndexOf(",")); - return Convert.ToInt64(timeStamp).ToString(); - }*/ - /// /// Generate a nonce /// @@ -401,15 +424,19 @@ namespace GreenshotPlugin.Core { Exception e = new Exception("The request token is not set"); throw e; } - - OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(this, browserTitle); + LOG.DebugFormat("Opening browser for URL: {0}", AuthorizationLink); + OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(this, browserTitle, BrowserWidth, BrowserHeight); oAuthLoginForm.ShowDialog(); Token = oAuthLoginForm.Token; - Verifier = oAuthLoginForm.Verifier; - if (!string.IsNullOrEmpty(Verifier)) { - return Token; + if (CheckVerifier) { + Verifier = oAuthLoginForm.Verifier; + if (!string.IsNullOrEmpty(Verifier)) { + return Token; + } else { + return null; + } } else { - return null; + return Token; } } @@ -418,7 +445,7 @@ namespace GreenshotPlugin.Core { /// /// The access token. public String getAccessToken() { - if (string.IsNullOrEmpty(Token) || string.IsNullOrEmpty(Verifier)) { + if (string.IsNullOrEmpty(Token) || (CheckVerifier && string.IsNullOrEmpty(Verifier))) { Exception e = new Exception("The request token and verifier were not set"); throw e; } @@ -472,7 +499,7 @@ namespace GreenshotPlugin.Core { postData += "&"; } qs[key] = NetworkHelper.UrlDecode(qs[key]); - qs[key] = UrlEncodeSpecial(qs[key]); + qs[key] = UrlEncode3986(qs[key]); postData += key + "=" + qs[key]; } @@ -492,7 +519,7 @@ namespace GreenshotPlugin.Core { string callback = ""; if (url.ToString().Contains(RequestTokenUrl)) { - callback = _callbackUrl; + callback = CallbackUrl; } //Generate Signature diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs index 4b7587e1b..92325f1e9 100644 --- a/GreenshotPlugin/Core/WindowsHelper.cs +++ b/GreenshotPlugin/Core/WindowsHelper.cs @@ -333,7 +333,18 @@ namespace GreenshotPlugin.Core { } return null; } - + + /// + /// Retrieve the children with mathing classname + /// + public IEnumerable GetChilden(string childClassname) { + foreach (WindowDetails child in Children) { + if (childClassname.Equals(child.ClassName)) { + yield return child; + } + } + } + public IntPtr ParentHandle { get { if (parentHandle == IntPtr.Zero) {