mirror of
https://github.com/greenshot/greenshot.git
synced 2025-01-10 15:52:48 -08:00
410 lines
12 KiB
C#
410 lines
12 KiB
C#
|
|
/*
|
|
* 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 Greenshot.IniFile;
|
|
using GreenshotJiraPlugin;
|
|
using GreenshotPlugin.Controls;
|
|
using GreenshotPlugin.Core;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
namespace Jira {
|
|
#region transport classes
|
|
public class JiraFilter {
|
|
public JiraFilter(string name, string id) {
|
|
this.Name = name;
|
|
this.Id = id;
|
|
}
|
|
public string Name {
|
|
get;
|
|
set;
|
|
}
|
|
public string Id {
|
|
get;
|
|
set;
|
|
}
|
|
}
|
|
|
|
public class JiraIssue {
|
|
public JiraIssue(string key, DateTime? created, string reporter, string assignee, string project, string summary, string description, string environment, string [] attachmentNames) {
|
|
this.Key = key;
|
|
this.Created = created;
|
|
this.Reporter = reporter;
|
|
this.Assignee = assignee;
|
|
this.Project = project;
|
|
this.Summary = summary;
|
|
this.Description = description;
|
|
this.Environment = environment;
|
|
this.AttachmentNames = attachmentNames;
|
|
}
|
|
public string Key {
|
|
get;
|
|
set;
|
|
}
|
|
public DateTime? Created {
|
|
get;
|
|
private set;
|
|
}
|
|
public string Reporter {
|
|
get;
|
|
private set;
|
|
}
|
|
public string Assignee {
|
|
get;
|
|
private set;
|
|
}
|
|
public string Project {
|
|
get;
|
|
private set;
|
|
}
|
|
public string Summary {
|
|
get;
|
|
private set;
|
|
}
|
|
public string Description {
|
|
get;
|
|
private set;
|
|
}
|
|
public string Environment {
|
|
get;
|
|
private set;
|
|
}
|
|
public string[] AttachmentNames {
|
|
get;
|
|
private set;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public class JiraConnector : IDisposable {
|
|
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(JiraConnector));
|
|
private const string AUTH_FAILED_EXCEPTION_NAME = "com.atlassian.jira.rpc.exception.RemoteAuthenticationException";
|
|
private static JiraConfiguration config = IniConfig.GetIniSection<JiraConfiguration>();
|
|
public const string DEFAULT_POSTFIX = "/rpc/soap/jirasoapservice-v2?wsdl";
|
|
private string credentials;
|
|
private DateTime loggedInTime = DateTime.Now;
|
|
private bool loggedIn;
|
|
private JiraSoapServiceService jira;
|
|
private int timeout;
|
|
private string url;
|
|
private Cache<string, JiraIssue> jiraCache = new Cache<string, JiraIssue>(60 * config.Timeout);
|
|
private Cache<string, RemoteUser> userCache = new Cache<string, RemoteUser>(60 * config.Timeout);
|
|
private bool suppressBackgroundForm = false;
|
|
|
|
public void Dispose() {
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing) {
|
|
if (jira != null) {
|
|
logout();
|
|
}
|
|
|
|
if (disposing) {
|
|
if (jira != null) {
|
|
jira.Dispose();
|
|
jira = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public JiraConnector() : this(false) {
|
|
}
|
|
|
|
public JiraConnector(bool suppressBackgroundForm) {
|
|
this.url = config.Url;
|
|
this.timeout = config.Timeout;
|
|
this.suppressBackgroundForm = suppressBackgroundForm;
|
|
createService();
|
|
}
|
|
|
|
private void createService() {
|
|
if (!suppressBackgroundForm) {
|
|
new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait),
|
|
delegate() {
|
|
jira = new JiraSoapServiceService();
|
|
}
|
|
);
|
|
} else {
|
|
jira = new JiraSoapServiceService();
|
|
}
|
|
jira.Url = url;
|
|
jira.Proxy = NetworkHelper.CreateProxy(new Uri(url));
|
|
// Do not use:
|
|
//jira.AllowAutoRedirect = true;
|
|
jira.UserAgent = "Greenshot";
|
|
}
|
|
|
|
~JiraConnector() {
|
|
Dispose(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal login which catches the exceptions
|
|
/// </summary>
|
|
/// <returns>true if login was done sucessfully</returns>
|
|
private bool doLogin(string user, string password, bool suppressBackgroundForm) {
|
|
|
|
// This is what needs to be done
|
|
ThreadStart jiraLogin = delegate {
|
|
LOG.DebugFormat("Loggin in");
|
|
try {
|
|
this.credentials = jira.login(user, password);
|
|
} catch (Exception) {
|
|
if (!url.EndsWith("wsdl")) {
|
|
url = url + "/rpc/soap/jirasoapservice-v2?wsdl";
|
|
// recreate the service with the new url
|
|
createService();
|
|
this.credentials = jira.login(user, password);
|
|
// Worked, store the url in the configuration
|
|
config.Url = url;
|
|
IniConfig.Save();
|
|
} else {
|
|
throw;
|
|
}
|
|
}
|
|
|
|
LOG.DebugFormat("Logged in");
|
|
this.loggedInTime = DateTime.Now;
|
|
this.loggedIn = true;
|
|
|
|
};
|
|
// Here we do it
|
|
try {
|
|
if (!suppressBackgroundForm) {
|
|
new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait), jiraLogin);
|
|
} else {
|
|
jiraLogin.Invoke();
|
|
}
|
|
} catch (Exception e) {
|
|
// check if auth failed
|
|
if (e.Message.Contains(AUTH_FAILED_EXCEPTION_NAME)) {
|
|
return false;
|
|
}
|
|
// Not an authentication issue
|
|
this.loggedIn = false;
|
|
this.credentials = null;
|
|
e.Data.Add("user", user);
|
|
e.Data.Add("url", url);
|
|
throw;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void login() {
|
|
login(false);
|
|
}
|
|
public void login(bool suppressBackgroundForm) {
|
|
logout();
|
|
try {
|
|
// Get the system name, so the user knows where to login to
|
|
string systemName = url.Replace(DEFAULT_POSTFIX,"");
|
|
CredentialsDialog dialog = new CredentialsDialog(systemName);
|
|
dialog.Name = null;
|
|
while (dialog.Show(dialog.Name) == DialogResult.OK) {
|
|
if (doLogin(dialog.Name, dialog.Password, suppressBackgroundForm)) {
|
|
if (dialog.SaveChecked) {
|
|
dialog.Confirm(true);
|
|
}
|
|
return;
|
|
} else {
|
|
try {
|
|
dialog.Confirm(false);
|
|
} catch (ApplicationException e) {
|
|
// exception handling ...
|
|
LOG.Error("Problem using the credentials dialog", e);
|
|
}
|
|
// For every windows version after XP show an incorrect password baloon
|
|
dialog.IncorrectPassword = true;
|
|
// Make sure the dialog is display, the password was false!
|
|
dialog.AlwaysDisplay = true;
|
|
}
|
|
}
|
|
} catch (ApplicationException e) {
|
|
// exception handling ...
|
|
LOG.Error("Problem using the credentials dialog", e);
|
|
}
|
|
}
|
|
|
|
public void logout() {
|
|
if (credentials != null) {
|
|
jira.logout(credentials);
|
|
credentials = null;
|
|
loggedIn = false;
|
|
}
|
|
}
|
|
|
|
private void checkCredentials() {
|
|
if (loggedIn) {
|
|
if (loggedInTime.AddMinutes(timeout-1).CompareTo(DateTime.Now) < 0) {
|
|
logout();
|
|
login();
|
|
}
|
|
} else {
|
|
login();
|
|
}
|
|
}
|
|
|
|
public bool isLoggedIn {
|
|
get {
|
|
return loggedIn;
|
|
}
|
|
}
|
|
|
|
public JiraFilter[] getFilters() {
|
|
List<JiraFilter> filters = new List<JiraFilter>();
|
|
checkCredentials();
|
|
RemoteFilter[] remoteFilters = jira.getSavedFilters(credentials);
|
|
foreach (RemoteFilter remoteFilter in remoteFilters) {
|
|
filters.Add(new JiraFilter(remoteFilter.name, remoteFilter.id));
|
|
}
|
|
return filters.ToArray();
|
|
}
|
|
|
|
private JiraIssue createDummyErrorIssue(Exception e) {
|
|
// Creating bogus jira to indicate a problem
|
|
return new JiraIssue("error", DateTime.Now, "error", "error", "error", e.Message, "error", "error", null);
|
|
}
|
|
|
|
public JiraIssue getIssue(string key) {
|
|
JiraIssue jiraIssue = null;
|
|
if (jiraCache.Contains(key)) {
|
|
jiraIssue = jiraCache[key];
|
|
}
|
|
if (jiraIssue == null) {
|
|
checkCredentials();
|
|
try {
|
|
RemoteIssue issue = jira.getIssue(credentials, key);
|
|
jiraIssue = new JiraIssue(issue.key, issue.created, getUserFullName(issue.reporter), getUserFullName(issue.assignee), issue.project, issue.summary, issue.description, issue.environment, issue.attachmentNames);
|
|
jiraCache.Add(key, jiraIssue);
|
|
} catch (Exception e) {
|
|
LOG.Error("Problem retrieving Jira: " + key, e);
|
|
}
|
|
}
|
|
return jiraIssue;
|
|
}
|
|
|
|
public JiraIssue[] getIssuesForFilter(string filterId) {
|
|
List<JiraIssue> issuesToReturn = new List<JiraIssue>();
|
|
checkCredentials();
|
|
try {
|
|
RemoteIssue[] issues = jira.getIssuesFromFilter(credentials, filterId);
|
|
|
|
#region Username cache update
|
|
List<string> users = new List<string>();
|
|
foreach (RemoteIssue issue in issues) {
|
|
if (issue.reporter != null && !hasUser(issue.reporter) && !users.Contains(issue.reporter)) {
|
|
users.Add(issue.reporter);
|
|
}
|
|
if (issue.assignee != null && !hasUser(issue.assignee) && !users.Contains(issue.assignee)) {
|
|
users.Add(issue.assignee);
|
|
}
|
|
}
|
|
int taskCount = users.Count;
|
|
if (taskCount > 0) {
|
|
ManualResetEvent doneEvent = new ManualResetEvent(false);
|
|
for (int i = 0; i < users.Count; i++) {
|
|
ThreadPool.QueueUserWorkItem(delegate(object name) {
|
|
LOG.InfoFormat("Retrieving {0}", name);
|
|
getUserFullName((string)name);
|
|
if (Interlocked.Decrement(ref taskCount) == 0) {
|
|
doneEvent.Set();
|
|
}
|
|
}, users[i]);
|
|
}
|
|
doneEvent.WaitOne();
|
|
}
|
|
#endregion
|
|
|
|
foreach (RemoteIssue issue in issues) {
|
|
try {
|
|
JiraIssue jiraIssue = new JiraIssue(issue.key, issue.created, getUserFullName(issue.reporter), getUserFullName(issue.assignee), issue.project, issue.summary, issue.description, "", issue.attachmentNames);
|
|
issuesToReturn.Add(jiraIssue);
|
|
} catch (Exception e) {
|
|
LOG.Error("Problem retrieving Jira: " + issue.key, e);
|
|
JiraIssue jiraIssue = createDummyErrorIssue(e);
|
|
jiraIssue.Key = issue.key;
|
|
issuesToReturn.Add(jiraIssue);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
LOG.Error("Problem retrieving Jiras for Filter: " + filterId, e);
|
|
issuesToReturn.Add(createDummyErrorIssue(e));
|
|
}
|
|
return issuesToReturn.ToArray(); ;
|
|
}
|
|
|
|
public string getURL(string issueKey) {
|
|
return url.Replace(DEFAULT_POSTFIX,"") + "/browse/" + issueKey;
|
|
}
|
|
|
|
public void addAttachment(string issueKey, string filename, IBinaryContainer attachment) {
|
|
checkCredentials();
|
|
try {
|
|
jira.addBase64EncodedAttachmentsToIssue(credentials, issueKey, new string[] { filename }, new string[] { attachment.ToBase64String(Base64FormattingOptions.InsertLineBreaks) });
|
|
} catch (Exception ex1) {
|
|
LOG.WarnFormat("Failed to upload by using method addBase64EncodedAttachmentsToIssue, error was {0}", ex1.Message);
|
|
try {
|
|
LOG.Warn("Trying addAttachmentsToIssue instead");
|
|
jira.addAttachmentsToIssue(credentials, issueKey, new string[] { filename }, (sbyte[])(Array)attachment.ToByteArray());
|
|
} catch (Exception ex2) {
|
|
LOG.WarnFormat("Failed to use alternative method, error was: {0}", ex2.Message);
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void addComment(string issueKey, string commentString) {
|
|
RemoteComment comment = new RemoteComment();
|
|
comment.body = commentString;
|
|
checkCredentials();
|
|
jira.addComment(credentials, issueKey, comment);
|
|
}
|
|
|
|
private bool hasUser(string user) {
|
|
if (user != null) {
|
|
return userCache.Contains(user);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private string getUserFullName(string user) {
|
|
string fullname = null;
|
|
if (user != null) {
|
|
if (userCache.Contains(user)) {
|
|
fullname = userCache[user].fullname;
|
|
} else {
|
|
checkCredentials();
|
|
RemoteUser remoteUser = jira.getUser(credentials, user);
|
|
userCache.Add(user, remoteUser);
|
|
fullname = remoteUser.fullname;
|
|
}
|
|
} else {
|
|
fullname = "Not assigned";
|
|
}
|
|
return fullname;
|
|
}
|
|
}
|
|
} |