mirror of
https://github.com/greenshot/greenshot
synced 2025-08-21 14:03:23 -07:00
"Merged" 0.8 with HEAD, so we can continue developing
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1282 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
174f653a5a
commit
f3b0878b02
539 changed files with 86855 additions and 0 deletions
726
GreenshotPlugin/Core/ConfigHelper.cs
Normal file
726
GreenshotPlugin/Core/ConfigHelper.cs
Normal file
|
@ -0,0 +1,726 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// Attribute for telling that this class is linked to a section in the ini-configuration
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
|
||||
public class IniSectionAttribute : Attribute {
|
||||
private string name;
|
||||
public IniSectionAttribute(string name) {
|
||||
this.name = name;
|
||||
}
|
||||
public string Description;
|
||||
public string Name {
|
||||
get {return name;}
|
||||
set {name = value;}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute for telling that a field is linked to a property in the ini-configuration selection
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)]
|
||||
public class IniPropertyAttribute : Attribute {
|
||||
private string name;
|
||||
public IniPropertyAttribute(string name) {
|
||||
this.name = name;
|
||||
}
|
||||
public string Description;
|
||||
public string Separator = ",";
|
||||
public string DefaultValue;
|
||||
public string Name {
|
||||
get {return name;}
|
||||
set {name = value;}
|
||||
}
|
||||
}
|
||||
public static class IniReader{
|
||||
private const string SECTION_START = "[";
|
||||
private const string SECTION_END = "]";
|
||||
private const string COMMENT = ";";
|
||||
private static char[] ASSIGNMENT = new char[] { '=' };
|
||||
|
||||
/**
|
||||
* Read an ini file to a Dictionary, each key is a section and the value is a Dictionary with name and values.
|
||||
*/
|
||||
public static Dictionary<string, Dictionary<string, string>> read(string path, Encoding encoding) {
|
||||
Dictionary<string, Dictionary<string, string>> ini = new Dictionary<string, Dictionary<string,string>>();
|
||||
using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024)) {
|
||||
using (StreamReader reader = new StreamReader(fileStream, encoding)) {
|
||||
Dictionary<string, string> nameValues = new Dictionary<string, string>();
|
||||
while (!reader.EndOfStream) {
|
||||
string line = reader.ReadLine();
|
||||
if (line != null) {
|
||||
string cleanLine = line.Trim();
|
||||
if (cleanLine.Length == 0 || cleanLine.StartsWith(COMMENT)) {
|
||||
continue;
|
||||
}
|
||||
if (cleanLine.StartsWith(SECTION_START)) {
|
||||
string section = line.Replace(SECTION_START, "").Replace(SECTION_END, "").Trim();
|
||||
nameValues = new Dictionary<string, string>();
|
||||
ini.Add(section, nameValues);
|
||||
} else {
|
||||
string[] keyvalueSplitter = line.Split(ASSIGNMENT, 2);
|
||||
string name = keyvalueSplitter[0];
|
||||
string inivalue = keyvalueSplitter.Length > 1 ? keyvalueSplitter[1] : null;
|
||||
if (nameValues.ContainsKey(name)) {
|
||||
nameValues[name] = inivalue;
|
||||
} else {
|
||||
nameValues.Add(name, inivalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ini;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all IniSections
|
||||
/// </summary>
|
||||
public abstract class IniSection {
|
||||
/// Flag to specify if values have been changed
|
||||
public bool IsDirty = false;
|
||||
|
||||
/// <summary>
|
||||
/// Supply values we can't put as defaults
|
||||
/// </summary>
|
||||
/// <param name="property">The property to return a default for</param>
|
||||
/// <returns>object with the default value for the supplied property</returns>
|
||||
public virtual object GetDefault(string property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called before converting the property, making to possible to correct a certain value
|
||||
/// Can be used when migration is needed
|
||||
/// </summary>
|
||||
/// <param name="propertyName">The name of the property</param>
|
||||
/// <param name="propertyValue">The string value of the property</param>
|
||||
/// <returns>string with the propertyValue, modified or not...</returns>
|
||||
public virtual string PreCheckValue(string propertyName, string propertyValue) {
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called after reading the configuration, so eventually some corrections can be made
|
||||
/// </summary>
|
||||
public virtual void PostCheckValues() {
|
||||
}
|
||||
}
|
||||
|
||||
public class IniConfig {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IniConfig));
|
||||
private const string CONFIG_FILE_NAME = "greenshot.ini";
|
||||
private const string DEFAULTS_CONFIG_FILE_NAME = "greenshot-defaults.ini";
|
||||
private const string FIXED_CONFIG_FILE_NAME = "greenshot-fixed.ini";
|
||||
private const string SUBDIRECTORY_NAME = "Greenshot";
|
||||
private static FileSystemWatcher watcher;
|
||||
|
||||
/// <summary>
|
||||
/// Static code for loading
|
||||
/// </summary>
|
||||
static IniConfig() {
|
||||
iniLocation = CreateIniLocation(CONFIG_FILE_NAME);
|
||||
// Load the defaults
|
||||
Read(CreateIniLocation(DEFAULTS_CONFIG_FILE_NAME));
|
||||
// Load the normal
|
||||
Read(CreateIniLocation(iniLocation));
|
||||
// Load the fixed settings
|
||||
Read(CreateIniLocation(FIXED_CONFIG_FILE_NAME));
|
||||
WatchConfigFile(true);
|
||||
}
|
||||
|
||||
private static string iniLocation = null;
|
||||
private static Dictionary<string, IniSection> sectionMap = new Dictionary<string, IniSection>();
|
||||
private static Dictionary<string, Dictionary<string, string >> iniProperties = new Dictionary<string, Dictionary<string, string>>();
|
||||
public static event FileSystemEventHandler IniChanged;
|
||||
|
||||
private static void WatchConfigFile(bool sendEvents) {
|
||||
// Wait with watching untill the file is there
|
||||
if (Directory.Exists(Path.GetDirectoryName(iniLocation))) {
|
||||
if (watcher == null) {
|
||||
LOG.DebugFormat("Starting FileSystemWatcher for {0}", iniLocation);
|
||||
// Monitor the ini file
|
||||
watcher = new FileSystemWatcher();
|
||||
watcher.Path = Path.GetDirectoryName(iniLocation);
|
||||
watcher.Filter = "*.ini";
|
||||
watcher.NotifyFilter = NotifyFilters.LastWrite;
|
||||
watcher.Changed += new FileSystemEventHandler(ConfigFileChanged);
|
||||
}
|
||||
}
|
||||
if (watcher != null) {
|
||||
watcher.EnableRaisingEvents = sendEvents;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigFileChanged(object source, FileSystemEventArgs e) {
|
||||
if (iniLocation.Equals(e.FullPath)) {
|
||||
LOG.InfoFormat("Config file {0} was changed, reloading", e.FullPath);
|
||||
|
||||
// Try to reread the configuration
|
||||
int retries = 10;
|
||||
bool configRead = false;
|
||||
while(!configRead && retries != 0) {
|
||||
try {
|
||||
IniConfig.Reload();
|
||||
configRead = true;
|
||||
} catch (IOException) {
|
||||
retries--;
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
if (configRead && IniChanged != null) {
|
||||
IniChanged.Invoke(source, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create the location of the configuration file
|
||||
/// </summary>
|
||||
private static string CreateIniLocation(string configFilename) {
|
||||
// check if file is in the same location as started from, if this is the case
|
||||
// we will use this file instead of the Applicationdate folder
|
||||
// Done for Feature Request #2741508
|
||||
if (File.Exists(Path.Combine(Application.StartupPath, configFilename))) {
|
||||
return Path.Combine(Application.StartupPath, configFilename);
|
||||
}
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), SUBDIRECTORY_NAME + @"\" + configFilename);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reload the Ini file
|
||||
/// </summary>
|
||||
public static void Reload() {
|
||||
// Load the normal
|
||||
Read(iniLocation);
|
||||
// Load the fixed settings
|
||||
Read(CreateIniLocation(FIXED_CONFIG_FILE_NAME));
|
||||
foreach(IniSection section in sectionMap.Values) {
|
||||
FillIniSection(section);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the ini file into the Dictionary
|
||||
/// </summary>
|
||||
/// <param name="iniLocation">Path & Filename of ini file</param>
|
||||
private static void Read(string iniLocation) {
|
||||
if (!File.Exists(iniLocation)) {
|
||||
LOG.Info("Can't find file: " + iniLocation);
|
||||
return;
|
||||
}
|
||||
LOG.Info("Reading ini-properties from file: " + iniLocation);
|
||||
iniProperties = IniReader.read(iniLocation, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A generic method which returns an instance of the supplied type, filled with it's configuration
|
||||
/// </summary>
|
||||
/// <returns>Filled instance of IniSection type which was supplied</returns>
|
||||
public static T GetIniSection<T>() where T : IniSection {
|
||||
T section;
|
||||
|
||||
Type iniSectionType = typeof(T);
|
||||
string sectionName = getSectionName(iniSectionType);
|
||||
if (sectionMap.ContainsKey(sectionName)) {
|
||||
LOG.Debug("Returning pre-mapped section " + sectionName);
|
||||
section = (T)sectionMap[sectionName];
|
||||
} else {
|
||||
// Create instance of this type
|
||||
section = (T)Activator.CreateInstance(iniSectionType);
|
||||
|
||||
// Store for later save & retrieval
|
||||
sectionMap.Add(sectionName, section);
|
||||
FillIniSection(section);
|
||||
LOG.Debug("Returning newly mapped section " + sectionName);
|
||||
}
|
||||
if (section.IsDirty) {
|
||||
IniConfig.Save();
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
private static void FillIniSection(IniSection section) {
|
||||
Type iniSectionType = section.GetType();
|
||||
string sectionName = getSectionName(iniSectionType);
|
||||
// Get the properties for the section
|
||||
Dictionary<string, string> properties = null;
|
||||
if (iniProperties.ContainsKey(sectionName)) {
|
||||
properties = iniProperties[sectionName];
|
||||
} else {
|
||||
iniProperties.Add(sectionName, new Dictionary<string, string>());
|
||||
properties = iniProperties[sectionName];
|
||||
}
|
||||
|
||||
// Iterate over the fields and fill them
|
||||
FieldInfo[] fields = iniSectionType.GetFields();
|
||||
foreach(FieldInfo field in fields) {
|
||||
if (Attribute.IsDefined(field, typeof(IniPropertyAttribute))) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)field.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
string propertyName = iniPropertyAttribute.Name;
|
||||
string propertyDefaultValue = iniPropertyAttribute.DefaultValue;
|
||||
string fieldSeparator = iniPropertyAttribute.Separator;
|
||||
// Get the type, or the underlying type for nullables
|
||||
Type fieldType = field.FieldType;
|
||||
|
||||
// Get the value from the ini file, if there is none take the default
|
||||
if (!properties.ContainsKey(propertyName) && propertyDefaultValue != null) {
|
||||
// Mark as dirty, we didn't use properties from the file (even defaults from the default file are allowed)
|
||||
section.IsDirty = true;
|
||||
LOG.Debug("Passing default: " + propertyName + "=" + propertyDefaultValue);
|
||||
}
|
||||
|
||||
// Try to get the field value from the properties or use the default value
|
||||
object fieldValue = null;
|
||||
try {
|
||||
fieldValue = CreateFieldValue(fieldType, section, sectionName, propertyName, propertyDefaultValue, fieldSeparator);
|
||||
} catch (Exception e) {
|
||||
LOG.Warn("Couldn't parse field: " + sectionName + "." + propertyName, e);
|
||||
}
|
||||
|
||||
// If still no value, check if the GetDefault delivers a value
|
||||
if (fieldValue == null) {
|
||||
// Use GetDefault to fill the field if none is set
|
||||
fieldValue = section.GetDefault(propertyName);
|
||||
}
|
||||
|
||||
// Set the value
|
||||
try {
|
||||
field.SetValue(section,fieldValue);
|
||||
} catch (Exception e) {
|
||||
LOG.Warn("Couldn't set field: " + sectionName + "." + propertyName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for creating a value
|
||||
/// </summary>
|
||||
/// <param name="fieldType">Type of the value to create</param>
|
||||
/// <param name="propertyValue">Value as string</param>
|
||||
/// <returns>object instance of the value</returns>
|
||||
private static object CreateFieldValue(Type fieldType, IniSection section, string sectionName, string propertyName, string defaultValue, string arraySeparator) {
|
||||
Dictionary<string, string> properties = iniProperties[sectionName];
|
||||
bool defaultUsed = false;
|
||||
string propertyValue = null;
|
||||
if (properties.ContainsKey(propertyName) && properties[propertyName] != null) {
|
||||
propertyValue = section.PreCheckValue(propertyName, properties[propertyName]);
|
||||
} else if (defaultValue != null && defaultValue.Trim().Length != 0) {
|
||||
propertyValue = defaultValue;
|
||||
defaultUsed = true;
|
||||
} else {
|
||||
LOG.DebugFormat("Property {0} has no value or default value", propertyName);
|
||||
}
|
||||
|
||||
// Now set the value
|
||||
if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(List<>)) {
|
||||
object list = Activator.CreateInstance(fieldType);
|
||||
// Logic for List<>
|
||||
if (propertyValue == null) {
|
||||
return list;
|
||||
}
|
||||
string[] arrayValues = propertyValue.Split(new string[] {arraySeparator}, StringSplitOptions.None);
|
||||
if (arrayValues == null || arrayValues.Length == 0) {
|
||||
return list;
|
||||
}
|
||||
bool addedElements = false;
|
||||
bool parseProblems = false;
|
||||
MethodInfo addMethodInfo = fieldType.GetMethod("Add");
|
||||
|
||||
foreach(string arrayValue in arrayValues) {
|
||||
if (arrayValue != null && arrayValue.Length > 0) {
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertValueToFieldType(fieldType.GetGenericArguments()[0], arrayValue);
|
||||
} catch (Exception e) {
|
||||
LOG.Error("Problem converting " + arrayValue + " to type " + fieldType.FullName, e);
|
||||
parseProblems = true;
|
||||
}
|
||||
if (newValue != null) {
|
||||
addMethodInfo.Invoke(list, new object[] {newValue});
|
||||
addedElements = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try to fallback on a default
|
||||
if (!addedElements && parseProblems) {
|
||||
try {
|
||||
object fallbackValue = ConvertValueToFieldType(fieldType.GetGenericArguments()[0], defaultValue);
|
||||
addMethodInfo.Invoke(list, new object[] {fallbackValue});
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
LOG.Error("Problem converting " + defaultValue + " to type " + fieldType.FullName, e);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
} else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
// Logic for Dictionary<,>
|
||||
Type type1 = fieldType.GetGenericArguments()[0];
|
||||
Type type2 = fieldType.GetGenericArguments()[1];
|
||||
LOG.Info(String.Format("Found Dictionary<{0},{1}>",type1.Name, type2.Name));
|
||||
object dictionary = Activator.CreateInstance(fieldType);
|
||||
MethodInfo addMethodInfo = fieldType.GetMethod("Add");
|
||||
bool addedElements = false;
|
||||
foreach(string key in properties.Keys) {
|
||||
if (key != null && key.StartsWith(propertyName + ".")) {
|
||||
// What "key" do we need to store it under?
|
||||
string subPropertyName = key.Substring(propertyName.Length + 1);
|
||||
string stringValue = properties[key];
|
||||
object newValue1 = null;
|
||||
object newValue2 = null;
|
||||
try {
|
||||
newValue1 = ConvertValueToFieldType(type1, subPropertyName);
|
||||
} catch (Exception e) {
|
||||
LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e);
|
||||
}
|
||||
try {
|
||||
newValue2 = ConvertValueToFieldType(type2, stringValue);
|
||||
} catch (Exception e) {
|
||||
LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e);
|
||||
}
|
||||
addMethodInfo.Invoke(dictionary, new object[] {newValue1, newValue2});
|
||||
addedElements = true;
|
||||
}
|
||||
}
|
||||
// No need to return something that isn't filled!
|
||||
if (addedElements) {
|
||||
return dictionary;
|
||||
}
|
||||
} else {
|
||||
if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
|
||||
// We are dealing with a generic type that is nullable
|
||||
fieldType = Nullable.GetUnderlyingType(fieldType);
|
||||
}
|
||||
object newValue = null;
|
||||
try {
|
||||
newValue = ConvertValueToFieldType(fieldType, propertyValue);
|
||||
} catch (Exception e1) {
|
||||
newValue = null;
|
||||
if (!defaultUsed) {
|
||||
try {
|
||||
newValue = ConvertValueToFieldType(fieldType, defaultValue);
|
||||
} catch (Exception e2) {
|
||||
LOG.Error("Problem converting " + propertyValue + " to type " + fieldType.FullName, e2);
|
||||
}
|
||||
} else {
|
||||
LOG.Error("Problem converting " + propertyValue + " to type " + fieldType.FullName, e1);
|
||||
}
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object ConvertValueToFieldType(Type fieldType, string valueString) {
|
||||
if (valueString == null) {
|
||||
return null;
|
||||
}
|
||||
if (fieldType == typeof(string)) {
|
||||
return valueString;
|
||||
} else if (fieldType == typeof(bool) || fieldType == typeof(bool?)) {
|
||||
if (valueString.Length > 0) {
|
||||
return bool.Parse(valueString);
|
||||
}
|
||||
} else if (fieldType == typeof(int) || fieldType == typeof(int?)) {
|
||||
if (valueString.Length > 0) {
|
||||
return int.Parse(valueString);
|
||||
}
|
||||
} else if (fieldType == typeof(uint) || fieldType == typeof(uint?)) {
|
||||
if (valueString.Length > 0) {
|
||||
return uint.Parse(valueString);
|
||||
}
|
||||
return 0;
|
||||
} else if (fieldType == typeof(Point)) {
|
||||
if (valueString.Length > 0) {
|
||||
string[] pointValues = valueString.Split(new Char[] {','});
|
||||
int x = int.Parse(pointValues[0].Trim());
|
||||
int y = int.Parse(pointValues[1].Trim());
|
||||
return new Point(x, y);
|
||||
}
|
||||
} else if (fieldType == typeof(DateTime)) {
|
||||
if (valueString.Length > 0) {
|
||||
return DateTime.Parse(valueString);
|
||||
}
|
||||
} else if (fieldType == typeof(Size)) {
|
||||
if (valueString.Length > 0) {
|
||||
string[] sizeValues = valueString.Split(new Char[] {','});
|
||||
int width = int.Parse(sizeValues[0].Trim());
|
||||
int height = int.Parse(sizeValues[1].Trim());
|
||||
return new Size(width, height);
|
||||
}
|
||||
} else if (fieldType == typeof(Rectangle)) {
|
||||
if (valueString.Length > 0) {
|
||||
string[] rectValues = valueString.Split(new Char[] {','});
|
||||
int x = int.Parse(rectValues[0].Trim());
|
||||
int y = int.Parse(rectValues[1].Trim());
|
||||
int width = int.Parse(rectValues[2].Trim());
|
||||
int height = int.Parse(rectValues[3].Trim());
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
} else if (fieldType == typeof(Color)) {
|
||||
if (valueString.Length > 0) {
|
||||
string[] colorValues = valueString.Split(new Char[] {','});
|
||||
int alpha = int.Parse(colorValues[0].Trim());
|
||||
int red = int.Parse(colorValues[1].Trim());
|
||||
int green = int.Parse(colorValues[2].Trim());
|
||||
int blue = int.Parse(colorValues[3].Trim());
|
||||
return Color.FromArgb(alpha, red, green, blue);
|
||||
}
|
||||
} else if (fieldType == typeof(object)) {
|
||||
if (valueString.Length > 0) {
|
||||
//LOG.Debug("Parsing: " + valueString);
|
||||
string[] values = valueString.Split(new Char[] {':'});
|
||||
//LOG.Debug("Type: " + values[0]);
|
||||
//LOG.Debug("Value: " + values[1]);
|
||||
Type fieldTypeForValue = Type.GetType(values[0], true);
|
||||
//LOG.Debug("Type after GetType: " + fieldTypeForValue);
|
||||
return ConvertValueToFieldType(fieldTypeForValue, values[1]);
|
||||
}
|
||||
} else if (fieldType.IsEnum) {
|
||||
if (valueString.Length > 0) {
|
||||
try {
|
||||
return Enum.Parse(fieldType, valueString);
|
||||
} catch (ArgumentException ae) {
|
||||
LOG.InfoFormat("Couldn't match {0} to {1}, trying case-insentive match", valueString, fieldType);
|
||||
foreach(Enum enumValue in Enum.GetValues(fieldType)) {
|
||||
if (enumValue.ToString().Equals(valueString, StringComparison.InvariantCultureIgnoreCase)) {
|
||||
LOG.Info("Match found...");
|
||||
return enumValue;
|
||||
}
|
||||
}
|
||||
throw ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string ConvertValueToString(Type fieldType, object valueObject) {
|
||||
if (valueObject == null) {
|
||||
// If there is nothing, deliver nothing!
|
||||
return "";
|
||||
}
|
||||
if (fieldType == typeof(Point)) {
|
||||
// Point to String
|
||||
Point p = (Point)valueObject;
|
||||
return String.Format("{0},{1}", p.X, p.Y);
|
||||
} else if (fieldType == typeof(Size)) {
|
||||
// Size to String
|
||||
Size size = (Size)valueObject;
|
||||
return String.Format("{0},{1}", size.Width, size.Height);
|
||||
} else if (fieldType == typeof(Rectangle)) {
|
||||
// Rectangle to String
|
||||
Rectangle rectangle = (Rectangle)valueObject;
|
||||
return String.Format("{0},{1},{2},{3}", rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
||||
} else if (fieldType == typeof(Color)) {
|
||||
// Color to String
|
||||
Color color = (Color)valueObject;
|
||||
return String.Format("{0},{1},{2},{3}", color.A, color.R, color.G, color.B);
|
||||
} else if (fieldType == typeof(object)) {
|
||||
// object to String, this is the hardest
|
||||
// Format will be "FQTypename[,Assemblyname]:Value"
|
||||
|
||||
// Get the type so we can call ourselves recursive
|
||||
Type valueType = valueObject.GetType();
|
||||
|
||||
// Get the value as string
|
||||
string ourValue = ConvertValueToString(valueType, valueObject);
|
||||
|
||||
// Get the valuetype as string
|
||||
string valueTypeName = valueType.FullName;
|
||||
// Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing)
|
||||
string assemblyName = valueType.Assembly.FullName;
|
||||
// correct assemblyName, this also has version information etc.
|
||||
if (assemblyName.StartsWith("Green")) {
|
||||
assemblyName = assemblyName.Substring(0,assemblyName.IndexOf(','));
|
||||
}
|
||||
return String.Format("{0},{1}:{2}", valueTypeName, assemblyName, ourValue);
|
||||
}
|
||||
// All other types
|
||||
return valueObject.ToString();
|
||||
}
|
||||
|
||||
private static string getSectionName(Type iniSectionType) {
|
||||
Attribute[] classAttributes = Attribute.GetCustomAttributes(iniSectionType);
|
||||
foreach(Attribute attribute in classAttributes) {
|
||||
if (attribute is IniSectionAttribute) {
|
||||
IniSectionAttribute iniSectionAttribute = (IniSectionAttribute)attribute;
|
||||
return iniSectionAttribute.Name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> getProperties(string section) {
|
||||
if (iniProperties.ContainsKey(section)) {
|
||||
return iniProperties[section];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetProperty(string section, string name) {
|
||||
Dictionary<string, string> properties = getProperties(section);
|
||||
if (properties != null && properties.ContainsKey(name)) {
|
||||
return properties[name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Split property with ',' and return the splitted string as a string[]
|
||||
/// </summary>
|
||||
public static string[] GetPropertyAsArray(string section, string key) {
|
||||
Dictionary<string, string> properties = getProperties(section);
|
||||
string value = GetProperty(section, key);
|
||||
if (value != null) {
|
||||
return value.Split(new Char[] {','});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool GetBoolProperty(string section, string key) {
|
||||
Dictionary<string, string> properties = getProperties(section);
|
||||
string value = GetProperty(section, key);
|
||||
return bool.Parse(value);
|
||||
}
|
||||
|
||||
public static int GetIntProperty(string section, string key) {
|
||||
Dictionary<string, string> properties = getProperties(section);
|
||||
string value = GetProperty(section, key);
|
||||
return int.Parse(value);
|
||||
}
|
||||
|
||||
public static void Save() {
|
||||
try {
|
||||
SaveInternally();
|
||||
} catch (Exception e) {
|
||||
LOG.Error("A problem occured while writing the configuration file to: " + iniLocation, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveInternally() {
|
||||
WatchConfigFile(false);
|
||||
|
||||
LOG.Info("Saving configuration to: " + iniLocation);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(iniLocation))) {
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(iniLocation));
|
||||
}
|
||||
TextWriter writer = new StreamWriter(iniLocation, false, Encoding.UTF8);
|
||||
foreach(IniSection section in sectionMap.Values) {
|
||||
Type classType = section.GetType();
|
||||
Attribute[] classAttributes = Attribute.GetCustomAttributes(classType);
|
||||
foreach(Attribute attribute in classAttributes) {
|
||||
if (attribute is IniSectionAttribute) {
|
||||
IniSectionAttribute iniSectionAttribute = (IniSectionAttribute)attribute;
|
||||
writer.WriteLine("; {0}", iniSectionAttribute.Description);
|
||||
writer.WriteLine("[{0}]", iniSectionAttribute.Name);
|
||||
FieldInfo[] fields = classType.GetFields();
|
||||
foreach(FieldInfo field in fields) {
|
||||
if (Attribute.IsDefined(field, typeof(IniPropertyAttribute))) {
|
||||
IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute)field.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0];
|
||||
writer.WriteLine("; {0}", iniPropertyAttribute.Description);
|
||||
object value = field.GetValue(section);
|
||||
Type fieldType = field.FieldType;
|
||||
if (value == null) {
|
||||
value = iniPropertyAttribute.DefaultValue;
|
||||
fieldType = typeof(string);
|
||||
}
|
||||
if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(List<>)) {
|
||||
Type valueType = fieldType.GetGenericArguments()[0];
|
||||
writer.Write("{0}=", iniPropertyAttribute.Name);
|
||||
int listCount = (int)fieldType.GetProperty("Count").GetValue(value, null);
|
||||
// Loop though generic list
|
||||
for (int index = 0; index < listCount; index++) {
|
||||
object item = fieldType.GetMethod("get_Item").Invoke(value, new object[] { index });
|
||||
|
||||
// Now you have an instance of the item in the generic list
|
||||
if (index < listCount -1) {
|
||||
writer.Write("{0}" + iniPropertyAttribute.Separator, ConvertValueToString(valueType, item));
|
||||
} else {
|
||||
writer.Write("{0}", ConvertValueToString(valueType, item));
|
||||
}
|
||||
}
|
||||
writer.WriteLine();
|
||||
} else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
|
||||
// Handle dictionaries.
|
||||
Type valueType1 = fieldType.GetGenericArguments()[0];
|
||||
Type valueType2 = fieldType.GetGenericArguments()[1];
|
||||
// Get the methods we need to deal with dictionaries.
|
||||
var keys = fieldType.GetProperty("Keys").GetValue(value, null);
|
||||
var item = fieldType.GetProperty("Item");
|
||||
var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null);
|
||||
var moveNext = enumerator.GetType().GetMethod("MoveNext");
|
||||
var current = enumerator.GetType().GetProperty("Current").GetGetMethod();
|
||||
// Get all the values.
|
||||
while ((bool)moveNext.Invoke(enumerator, null)) {
|
||||
var key = current.Invoke(enumerator, null);
|
||||
var valueObject = item.GetValue(value, new object[] { key });
|
||||
// Write to ini file!
|
||||
writer.WriteLine("{0}.{1}={2}", iniPropertyAttribute.Name, ConvertValueToString(valueType1, key), ConvertValueToString(valueType2, valueObject));
|
||||
}
|
||||
} else {
|
||||
writer.WriteLine("{0}={1}", iniPropertyAttribute.Name, ConvertValueToString(fieldType, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.WriteLine();
|
||||
section.IsDirty = false;
|
||||
}
|
||||
writer.WriteLine();
|
||||
// Write left over properties
|
||||
foreach(string sectionName in iniProperties.Keys) {
|
||||
// Check if the section is one that is "registered", if so skip it!
|
||||
if (!sectionMap.ContainsKey(sectionName)) {
|
||||
writer.WriteLine("; The section {0} is not registered, maybe a plugin hasn't claimed it due to errors or some functionality isn't used yet.", sectionName);
|
||||
// Write section name
|
||||
writer.WriteLine("[{0}]", sectionName);
|
||||
Dictionary<string, string> properties = iniProperties[sectionName];
|
||||
// Loop and write properties
|
||||
foreach(string propertyName in properties.Keys) {
|
||||
writer.WriteLine("{0}={1}", propertyName, properties[propertyName]);
|
||||
}
|
||||
writer.WriteLine();
|
||||
}
|
||||
}
|
||||
writer.Close();
|
||||
WatchConfigFile(true);
|
||||
}
|
||||
}
|
||||
}
|
196
GreenshotPlugin/Core/CoreConfiguration.cs
Normal file
196
GreenshotPlugin/Core/CoreConfiguration.cs
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
public enum Destination {
|
||||
Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail
|
||||
}
|
||||
public enum OutputFormat {
|
||||
bmp, gif, jpg, png, tiff
|
||||
}
|
||||
public enum WindowCaptureMode {
|
||||
Screen, GDI, Aero, AeroTransparent, Auto
|
||||
}
|
||||
public enum EmailFormat {
|
||||
TXT, HTML
|
||||
}
|
||||
public enum UpdateCheckInterval {
|
||||
Never,
|
||||
Daily,
|
||||
Weekly,
|
||||
Monthly
|
||||
}
|
||||
public enum EmailExport {
|
||||
AlwaysNew,
|
||||
TryOpenElseNew
|
||||
}
|
||||
/// <summary>
|
||||
/// Description of CoreConfiguration.
|
||||
/// </summary>
|
||||
[IniSection("Core", Description="Greenshot core configuration")]
|
||||
public class CoreConfiguration : IniSection {
|
||||
[IniProperty("Language", Description="The language in IETF format (e.g. en-EN)", DefaultValue="en-EN")]
|
||||
public string Language;
|
||||
|
||||
[IniProperty("RegionHotkey", Description="Hotkey for starting the region capture", DefaultValue="PrintScreen")]
|
||||
public string RegionHotkey;
|
||||
[IniProperty("WindowHotkey", Description="Hotkey for starting the window capture", DefaultValue="Alt + PrintScreen")]
|
||||
public string WindowHotkey;
|
||||
[IniProperty("FullscreenHotkey", Description="Hotkey for starting the fullscreen capture", DefaultValue="Ctrl + PrintScreen")]
|
||||
public string FullscreenHotkey;
|
||||
[IniProperty("LastregionHotkey", Description="Hotkey for starting the last region capture", DefaultValue="Shift + PrintScreen")]
|
||||
public string LastregionHotkey;
|
||||
[IniProperty("IEHotkey", Description="Hotkey for starting the IE capture", DefaultValue="Shift + Ctrl + PrintScreen")]
|
||||
public string IEHotkey;
|
||||
|
||||
[IniProperty("IsFirstLaunch", Description="Is this the first time launch?", DefaultValue="true")]
|
||||
public bool IsFirstLaunch;
|
||||
[IniProperty("Destinations", Separator=",", Description="Which destinations? Options are: Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail", DefaultValue="Editor")]
|
||||
public List<Destination> OutputDestinations = new List<Destination>();
|
||||
|
||||
[IniProperty("CaptureMousepointer", Description="Should the mouse be captured?", DefaultValue="true")]
|
||||
public bool CaptureMousepointer;
|
||||
[IniProperty("CaptureWindowsInteractive", Description="Use interactive window selection to capture? (false=Capture active window)", DefaultValue="false")]
|
||||
public bool CaptureWindowsInteractive;
|
||||
[IniProperty("CaptureDelay", Description="Capture delay in millseconds.", DefaultValue="100")]
|
||||
public int CaptureDelay;
|
||||
[IniProperty("WindowCaptureMode", Description="The capture mode used to capture a Window.", DefaultValue="Auto")]
|
||||
public WindowCaptureMode WindowCaptureMode;
|
||||
[IniProperty("DWMBackgroundColor", Description="The background color for a DWM window capture.")]
|
||||
public Color DWMBackgroundColor;
|
||||
|
||||
[IniProperty("PlayCameraSound", Description="Play a camera sound after taking a capture.", DefaultValue="false")]
|
||||
public bool PlayCameraSound = false;
|
||||
|
||||
[IniProperty("OutputFilePath", Description="Output file path.")]
|
||||
public string OutputFilePath;
|
||||
[IniProperty("OutputFileFilenamePattern", Description="Filename pattern for screenshot.", DefaultValue="${capturetime}_${title}")]
|
||||
public string OutputFileFilenamePattern;
|
||||
[IniProperty("OutputFileFormat", Description="Default file type for writing screenshots. (bmp, gif, jpg, png, tiff)", DefaultValue="png")]
|
||||
public OutputFormat OutputFileFormat = OutputFormat.png;
|
||||
[IniProperty("OutputFileReduceColors", Description="If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue="false")]
|
||||
public bool OutputFileReduceColors;
|
||||
|
||||
[IniProperty("OutputEMailFormat", Description="Default type for emails. (txt, html)", DefaultValue="html")]
|
||||
public EmailFormat OutputEMailFormat = EmailFormat.HTML;
|
||||
[IniProperty("OutputOutlookMethod", Description="How to export to outlook (AlwaysNew= always open a new one, TryOpenElseNew=look for open email else create a new)", DefaultValue="AlwaysNew")]
|
||||
public EmailExport OutputOutlookMethod;
|
||||
|
||||
[IniProperty("OutputFileCopyPathToClipboard", Description="When saving a screenshot, copy the path to the clipboard?", DefaultValue="true")]
|
||||
public bool OutputFileCopyPathToClipboard;
|
||||
[IniProperty("OutputFileAsFullpath", Description="SaveAs Full path?")]
|
||||
public string OutputFileAsFullpath;
|
||||
|
||||
[IniProperty("OutputFileJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
|
||||
public int OutputFileJpegQuality;
|
||||
[IniProperty("OutputFilePromptJpegQuality", Description="Ask for the JPEQ quality before saving?", DefaultValue="false")]
|
||||
public bool OutputFilePromptJpegQuality;
|
||||
[IniProperty("OutputFileIncrementingNumber", Description="The number for the %NUM% in the filename pattern, is increased automatically after each save.", DefaultValue="1")]
|
||||
public uint OutputFileIncrementingNumber;
|
||||
|
||||
[IniProperty("OutputPrintPromptOptions", Description="Ask for print options when printing?", DefaultValue="true")]
|
||||
public bool OutputPrintPromptOptions;
|
||||
[IniProperty("OutputPrintAllowRotate", Description="Allow rotating the picture for fitting on paper?", DefaultValue="true")]
|
||||
public bool OutputPrintAllowRotate;
|
||||
[IniProperty("OutputPrintAllowEnlarge", Description="Allow growing the picture for fitting on paper?", DefaultValue="true")]
|
||||
public bool OutputPrintAllowEnlarge;
|
||||
[IniProperty("OutputPrintAllowShrink", Description="Allow shrinking the picture for fitting on paper?", DefaultValue="true")]
|
||||
public bool OutputPrintAllowShrink;
|
||||
[IniProperty("OutputPrintCenter", Description="Center image when printing?", DefaultValue="true")]
|
||||
public bool OutputPrintCenter;
|
||||
[IniProperty("OutputPrintInverted", Description="Print image inverted (use e.g. for console captures)", DefaultValue="false")]
|
||||
public bool OutputPrintInverted;
|
||||
[IniProperty("OutputPrintTimestamp", Description="Print timestamp on print?", DefaultValue="true")]
|
||||
public bool OutputPrintTimestamp;
|
||||
[IniProperty("UseProxy", Description="Use your global proxy?", DefaultValue="True")]
|
||||
public bool UseProxy;
|
||||
[IniProperty("IECapture", Description="Enable/disable IE capture", DefaultValue="True")]
|
||||
public bool IECapture;
|
||||
|
||||
[IniProperty("IncludePlugins", Description="Comma separated list of Plugins which are allowed. If something in the list, than every plugin not in the list will not be loaded!")]
|
||||
public List<string> IncludePlugins;
|
||||
[IniProperty("ExcludePlugins", Description="Comma separated list of Plugins which are NOT allowed.")]
|
||||
public List<string> ExcludePlugins;
|
||||
|
||||
[IniProperty("UpdateCheckInterval", Description="How many days between every update check? (0=no checks)", DefaultValue="1")]
|
||||
public int UpdateCheckInterval;
|
||||
|
||||
[IniProperty("LastUpdateCheck", Description="Last update check")]
|
||||
public DateTime LastUpdateCheck;
|
||||
|
||||
// change to false for releases
|
||||
public bool CheckUnstable = true;
|
||||
|
||||
/// <summary>
|
||||
/// Supply values we can't put as defaults
|
||||
/// </summary>
|
||||
/// <param name="property">The property to return a default for</param>
|
||||
/// <returns>object with the default value for the supplied property</returns>
|
||||
public override object GetDefault(string property) {
|
||||
switch(property) {
|
||||
case "PluginWhitelist":
|
||||
case "PluginBacklist":
|
||||
return new List<string>();
|
||||
case "OutputFileAsFullpath":
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"dummy.png");
|
||||
case "OutputFilePath":
|
||||
return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
|
||||
case "DWMBackgroundColor":
|
||||
return Color.White;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called before converting the property, making to possible to correct a certain value
|
||||
/// Can be used when migration is needed
|
||||
/// </summary>
|
||||
/// <param name="propertyName">The name of the property</param>
|
||||
/// <param name="propertyValue">The string value of the property</param>
|
||||
/// <returns>string with the propertyValue, modified or not...</returns>
|
||||
public override string PreCheckValue(string propertyName, string propertyValue) {
|
||||
// Changed the separator, now we need to correct this
|
||||
if ("Destinations".Equals(propertyName)) {
|
||||
if (propertyValue != null) {
|
||||
return propertyValue.Replace('|',',');
|
||||
}
|
||||
}
|
||||
return base.PreCheckValue(propertyName, propertyValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will be called after reading the configuration, so eventually some corrections can be made
|
||||
/// </summary>
|
||||
public override void PostCheckValues() {
|
||||
if (OutputDestinations == null) {
|
||||
OutputDestinations = new List<Destination>();
|
||||
}
|
||||
if (OutputDestinations.Count == 0) {
|
||||
OutputDestinations.Add(Destination.Editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
608
GreenshotPlugin/Core/CredentialsHelper.cs
Normal file
608
GreenshotPlugin/Core/CredentialsHelper.cs
Normal file
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// The following code comes from: http://www.developerfusion.com/code/4693/using-the-credential-management-api/
|
||||
/// and is slightly modified so it works for us.
|
||||
/// As the "Stored usernames and passwords" which can be accessed by: Start-> Run and type "Control keymgr.dll"
|
||||
/// doesn't show all credentials use the tool here: http://www.microsoft.com/indonesia/msdn/credmgmt.aspx
|
||||
/// The following code is an example for a login, it will call the Authenticate with user/password
|
||||
/// which should return true if the login worked, false if not.
|
||||
/// private static bool Login(string system, string name) {
|
||||
/// try {
|
||||
/// CredentialsDialog dialog = new CredentialsDialog(system);
|
||||
/// dialog.Name = name;
|
||||
/// while (dialog.Show(dialog.Name) == DialogResult.OK) {
|
||||
/// if (Authenticate(dialog.Name, dialog.Password)) {
|
||||
/// if (dialog.SaveChecked) dialog.Confirm(true);
|
||||
/// return true;
|
||||
/// } else {
|
||||
/// try {
|
||||
/// dialog.Confirm(false);
|
||||
/// } catch (ApplicationException) {
|
||||
/// // exception handling ...
|
||||
/// }
|
||||
/// dialog.IncorrectPassword = true;
|
||||
/// }
|
||||
/// }
|
||||
/// } catch (ApplicationException) {
|
||||
/// // exception handling ...
|
||||
/// }
|
||||
/// return false;
|
||||
/// }
|
||||
/// </summary>
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>Encapsulates dialog functionality from the Credential Management API.</summary>
|
||||
public sealed class CredentialsDialog {
|
||||
[DllImport("gdi32.dll", SetLastError=true)]
|
||||
private static extern bool DeleteObject(IntPtr hObject);
|
||||
|
||||
/// <summary>The only valid bitmap height (in pixels) of a user-defined banner.</summary>
|
||||
private const int ValidBannerHeight = 60;
|
||||
|
||||
/// <summary>The only valid bitmap width (in pixels) of a user-defined banner.</summary>
|
||||
private const int ValidBannerWidth = 320;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
|
||||
/// with the specified target.</summary>
|
||||
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
|
||||
public CredentialsDialog(string target) : this(target, null) {
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
|
||||
/// with the specified target and caption.</summary>
|
||||
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
|
||||
/// <param name="caption">The caption of the dialog (null will cause a system default title to be used).</param>
|
||||
public CredentialsDialog(string target, string caption) : this(target, caption, null) {
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
|
||||
/// with the specified target, caption and message.</summary>
|
||||
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
|
||||
/// <param name="caption">The caption of the dialog (null will cause a system default title to be used).</param>
|
||||
/// <param name="message">The message of the dialog (null will cause a system default message to be used).</param>
|
||||
public CredentialsDialog(string target, string caption, string message) : this(target, caption, message, null) {
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
|
||||
/// with the specified target, caption, message and banner.</summary>
|
||||
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
|
||||
/// <param name="caption">The caption of the dialog (null will cause a system default title to be used).</param>
|
||||
/// <param name="message">The message of the dialog (null will cause a system default message to be used).</param>
|
||||
/// <param name="banner">The image to display on the dialog (null will cause a system default image to be used).</param>
|
||||
public CredentialsDialog(string target, string caption, string message, Image banner) {
|
||||
this.Target = target;
|
||||
this.Caption = caption;
|
||||
this.Message = message;
|
||||
this.Banner = banner;
|
||||
}
|
||||
|
||||
private bool _alwaysDisplay = false;
|
||||
/// <summary>
|
||||
/// Gets or sets if the dialog will be shown even if the credentials
|
||||
/// can be returned from an existing credential in the credential manager.
|
||||
/// </summary>
|
||||
public bool AlwaysDisplay {
|
||||
get {
|
||||
return _alwaysDisplay;
|
||||
}
|
||||
set {
|
||||
_alwaysDisplay = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _excludeCertificates = true;
|
||||
/// <summary>Gets or sets if the dialog is populated with name/password only.</summary>
|
||||
public bool ExcludeCertificates {
|
||||
get {
|
||||
return _excludeCertificates;
|
||||
}
|
||||
set {
|
||||
_excludeCertificates = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _persist = true;
|
||||
/// <summary>Gets or sets if the credentials are to be persisted in the credential manager.</summary>
|
||||
public bool Persist {
|
||||
get {
|
||||
return _persist;
|
||||
}
|
||||
set {
|
||||
_persist = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _incorrectPassword = false;
|
||||
/// <summary>Gets or sets if the incorrect password balloontip needs to be shown. Introduced AFTER Windows XP</summary>Gets></summary>
|
||||
public bool IncorrectPassword {
|
||||
get {
|
||||
return _incorrectPassword;
|
||||
}
|
||||
set {
|
||||
_incorrectPassword = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _keepName = false;
|
||||
/// <summary>Gets or sets if the name is read-only.</summary>
|
||||
public bool KeepName {
|
||||
get {
|
||||
return _keepName;
|
||||
}
|
||||
set {
|
||||
_keepName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _name = String.Empty;
|
||||
/// <summary>Gets or sets the name for the credentials.</summary>
|
||||
public string Name {
|
||||
get {
|
||||
return _name;
|
||||
}
|
||||
set {
|
||||
if (value != null) {
|
||||
if (value.Length > CREDUI.MAX_USERNAME_LENGTH) {
|
||||
string message = String.Format(
|
||||
Thread.CurrentThread.CurrentUICulture,
|
||||
"The name has a maximum length of {0} characters.",
|
||||
CREDUI.MAX_USERNAME_LENGTH);
|
||||
throw new ArgumentException(message, "Name");
|
||||
}
|
||||
}
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _password = String.Empty;
|
||||
/// <summary>Gets or sets the password for the credentials.</summary>
|
||||
public string Password {
|
||||
get {
|
||||
return _password;
|
||||
}
|
||||
set {
|
||||
if (value != null) {
|
||||
if (value.Length > CREDUI.MAX_PASSWORD_LENGTH) {
|
||||
string message = String.Format(
|
||||
Thread.CurrentThread.CurrentUICulture,
|
||||
"The password has a maximum length of {0} characters.",
|
||||
CREDUI.MAX_PASSWORD_LENGTH);
|
||||
throw new ArgumentException(message, "Password");
|
||||
}
|
||||
}
|
||||
_password = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveChecked = false;
|
||||
/// <summary>Gets or sets if the save checkbox status.</summary>
|
||||
public bool SaveChecked {
|
||||
get {
|
||||
return _saveChecked;
|
||||
}
|
||||
set {
|
||||
_saveChecked = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveDisplayed = true;
|
||||
/// <summary>Gets or sets if the save checkbox is displayed.</summary>
|
||||
/// <remarks>This value only has effect if Persist is true.</remarks>
|
||||
public bool SaveDisplayed {
|
||||
get {
|
||||
return _saveDisplayed;
|
||||
}
|
||||
set {
|
||||
_saveDisplayed = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _target = String.Empty;
|
||||
/// <summary>Gets or sets the name of the target for the credentials, typically a server name.</summary>
|
||||
public string Target {
|
||||
get {
|
||||
return _target;
|
||||
}
|
||||
set {
|
||||
if (value == null) {
|
||||
throw new ArgumentException("The target cannot be a null value.", "Target");
|
||||
} else if (value.Length > CREDUI.MAX_GENERIC_TARGET_LENGTH) {
|
||||
string message = String.Format(
|
||||
Thread.CurrentThread.CurrentUICulture,
|
||||
"The target has a maximum length of {0} characters.",
|
||||
CREDUI.MAX_GENERIC_TARGET_LENGTH);
|
||||
throw new ArgumentException(message, "Target");
|
||||
}
|
||||
_target = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _caption = String.Empty;
|
||||
/// <summary>Gets or sets the caption of the dialog.</summary>
|
||||
/// <remarks>A null value will cause a system default caption to be used.</remarks>
|
||||
public string Caption {
|
||||
get {
|
||||
return _caption;
|
||||
}
|
||||
set {
|
||||
if (value != null) {
|
||||
if (value.Length > CREDUI.MAX_CAPTION_LENGTH) {
|
||||
string message = String.Format(
|
||||
Thread.CurrentThread.CurrentUICulture,
|
||||
"The caption has a maximum length of {0} characters.",
|
||||
CREDUI.MAX_CAPTION_LENGTH);
|
||||
throw new ArgumentException(message, "Caption");
|
||||
}
|
||||
}
|
||||
_caption = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _message = String.Empty;
|
||||
/// <summary>Gets or sets the message of the dialog.</summary>
|
||||
/// <remarks>A null value will cause a system default message to be used.</remarks>
|
||||
public string Message {
|
||||
get {
|
||||
return _message;
|
||||
}
|
||||
set {
|
||||
if (value != null) {
|
||||
if (value.Length > CREDUI.MAX_MESSAGE_LENGTH) {
|
||||
string message = String.Format(
|
||||
Thread.CurrentThread.CurrentUICulture,
|
||||
"The message has a maximum length of {0} characters.",
|
||||
CREDUI.MAX_MESSAGE_LENGTH);
|
||||
throw new ArgumentException(message, "Message");
|
||||
}
|
||||
}
|
||||
_message = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Image _banner = null;
|
||||
/// <summary>Gets or sets the image to display on the dialog.</summary>
|
||||
/// <remarks>A null value will cause a system default image to be used.</remarks>
|
||||
public Image Banner {
|
||||
get {
|
||||
return _banner;
|
||||
}
|
||||
set {
|
||||
if (value != null) {
|
||||
if (value.Width != ValidBannerWidth) {
|
||||
throw new ArgumentException("The banner image width must be 320 pixels.", "Banner");
|
||||
}
|
||||
if (value.Height != ValidBannerHeight) {
|
||||
throw new ArgumentException("The banner image height must be 60 pixels.", "Banner");
|
||||
}
|
||||
}
|
||||
_banner = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog.</summary>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show() {
|
||||
return Show(null, this.Name, this.Password, this.SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified save checkbox status.</summary>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(bool saveChecked) {
|
||||
return Show(null, this.Name, this.Password, saveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified name.</summary>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(string name) {
|
||||
return Show(null, name, this.Password, this.SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified name and password.</summary>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(string name, string password) {
|
||||
return Show(null, name, password, this.SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified name, password and save checkbox status.</summary>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(string name, string password, bool saveChecked) {
|
||||
return Show(null, name, password, saveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner) {
|
||||
return Show(owner, this.Name, this.Password, this.SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner and save checkbox status.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner, bool saveChecked) {
|
||||
return Show(owner, this.Name, this.Password, saveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner, name and password.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner, string name, string password) {
|
||||
return Show(owner, name, password, this.SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner, name, password and save checkbox status.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner, string name, string password, bool saveChecked) {
|
||||
if ((Environment.OSVersion.Version.Major < 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor < 1))) {
|
||||
throw new ApplicationException("The Credential Management API requires Windows XP / Windows Server 2003 or later.");
|
||||
}
|
||||
this.Name = name;
|
||||
this.Password = password;
|
||||
this.SaveChecked = saveChecked;
|
||||
|
||||
return ShowDialog(owner);
|
||||
}
|
||||
|
||||
/// <summary>Confirmation action to be applied.</summary>
|
||||
/// <param name="value">True if the credentials should be persisted.</param>
|
||||
public void Confirm(bool value) {
|
||||
switch (CREDUI.ConfirmCredentials(this.Target, value)) {
|
||||
case CREDUI.ReturnCodes.NO_ERROR:
|
||||
break;
|
||||
|
||||
case CREDUI.ReturnCodes.ERROR_INVALID_PARAMETER:
|
||||
// for some reason, this is encountered when credentials are overwritten
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ApplicationException("Credential confirmation failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returns a DialogResult indicating the user action.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <remarks>
|
||||
/// Sets the name, password and SaveChecked accessors to the state of the dialog as it was dismissed by the user.
|
||||
/// </remarks>
|
||||
private DialogResult ShowDialog(IWin32Window owner) {
|
||||
// set the api call parameters
|
||||
StringBuilder name = new StringBuilder(CREDUI.MAX_USERNAME_LENGTH);
|
||||
name.Append(this.Name);
|
||||
|
||||
StringBuilder password = new StringBuilder(CREDUI.MAX_PASSWORD_LENGTH);
|
||||
password.Append(this.Password);
|
||||
|
||||
int saveChecked = Convert.ToInt32(this.SaveChecked);
|
||||
|
||||
CREDUI.INFO info = GetInfo(owner);
|
||||
CREDUI.FLAGS flags = GetFlags();
|
||||
|
||||
// make the api call
|
||||
CREDUI.ReturnCodes code = CREDUI.PromptForCredentials(
|
||||
ref info,
|
||||
this.Target,
|
||||
IntPtr.Zero, 0,
|
||||
name, CREDUI.MAX_USERNAME_LENGTH,
|
||||
password, CREDUI.MAX_PASSWORD_LENGTH,
|
||||
ref saveChecked,
|
||||
flags
|
||||
);
|
||||
|
||||
// clean up resources
|
||||
if (this.Banner != null) {
|
||||
DeleteObject(info.hbmBanner);
|
||||
}
|
||||
|
||||
// set the accessors from the api call parameters
|
||||
this.Name = name.ToString();
|
||||
this.Password = password.ToString();
|
||||
this.SaveChecked = Convert.ToBoolean(saveChecked);
|
||||
|
||||
return GetDialogResult(code);
|
||||
}
|
||||
|
||||
/// <summary>Returns the info structure for dialog display settings.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
private CREDUI.INFO GetInfo(IWin32Window owner) {
|
||||
CREDUI.INFO info = new CREDUI.INFO();
|
||||
if (owner != null) info.hwndParent = owner.Handle;
|
||||
info.pszCaptionText = this.Caption;
|
||||
info.pszMessageText = this.Message;
|
||||
if (this.Banner != null) {
|
||||
info.hbmBanner = new Bitmap(this.Banner, ValidBannerWidth, ValidBannerHeight).GetHbitmap();
|
||||
}
|
||||
info.cbSize = Marshal.SizeOf(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
/// <summary>Returns the flags for dialog display options.</summary>
|
||||
private CREDUI.FLAGS GetFlags() {
|
||||
CREDUI.FLAGS flags = CREDUI.FLAGS.GENERIC_CREDENTIALS;
|
||||
|
||||
if (this.IncorrectPassword) {
|
||||
flags = flags | CREDUI.FLAGS.INCORRECT_PASSWORD;
|
||||
}
|
||||
|
||||
if (this.AlwaysDisplay) {
|
||||
flags = flags | CREDUI.FLAGS.ALWAYS_SHOW_UI;
|
||||
}
|
||||
|
||||
if (this.ExcludeCertificates) {
|
||||
flags = flags | CREDUI.FLAGS.EXCLUDE_CERTIFICATES;
|
||||
}
|
||||
|
||||
if (this.Persist) {
|
||||
flags = flags | CREDUI.FLAGS.EXPECT_CONFIRMATION;
|
||||
if (this.SaveDisplayed) {
|
||||
flags = flags | CREDUI.FLAGS.SHOW_SAVE_CHECK_BOX;
|
||||
} else {
|
||||
flags = flags | CREDUI.FLAGS.PERSIST;
|
||||
}
|
||||
} else {
|
||||
flags = flags | CREDUI.FLAGS.DO_NOT_PERSIST;
|
||||
}
|
||||
|
||||
if (this.KeepName) {
|
||||
flags = flags | CREDUI.FLAGS.KEEP_USERNAME;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/// <summary>Returns a DialogResult from the specified code.</summary>
|
||||
/// <param name="code">The credential return code.</param>
|
||||
private DialogResult GetDialogResult(CREDUI.ReturnCodes code) {
|
||||
DialogResult result;
|
||||
switch (code) {
|
||||
case CREDUI.ReturnCodes.NO_ERROR:
|
||||
result = DialogResult.OK;
|
||||
break;
|
||||
case CREDUI.ReturnCodes.ERROR_CANCELLED:
|
||||
result = DialogResult.Cancel;
|
||||
break;
|
||||
case CREDUI.ReturnCodes.ERROR_NO_SUCH_LOGON_SESSION:
|
||||
throw new ApplicationException("No such logon session.");
|
||||
case CREDUI.ReturnCodes.ERROR_NOT_FOUND:
|
||||
throw new ApplicationException("Not found.");
|
||||
case CREDUI.ReturnCodes.ERROR_INVALID_ACCOUNT_NAME:
|
||||
throw new ApplicationException("Invalid account name.");
|
||||
case CREDUI.ReturnCodes.ERROR_INSUFFICIENT_BUFFER:
|
||||
throw new ApplicationException("Insufficient buffer.");
|
||||
case CREDUI.ReturnCodes.ERROR_INVALID_PARAMETER:
|
||||
throw new ApplicationException("Invalid parameter.");
|
||||
case CREDUI.ReturnCodes.ERROR_INVALID_FLAGS:
|
||||
throw new ApplicationException("Invalid flags.");
|
||||
default:
|
||||
throw new ApplicationException("Unknown credential result encountered.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CREDUI {
|
||||
private CREDUI() {
|
||||
}
|
||||
|
||||
/// <summary>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/authentication_constants.asp</summary>
|
||||
public const int MAX_MESSAGE_LENGTH = 100;
|
||||
public const int MAX_CAPTION_LENGTH = 100;
|
||||
public const int MAX_GENERIC_TARGET_LENGTH = 100;
|
||||
public const int MAX_DOMAIN_TARGET_LENGTH = 100;
|
||||
public const int MAX_USERNAME_LENGTH = 100;
|
||||
public const int MAX_PASSWORD_LENGTH = 100;
|
||||
|
||||
/// <summary>
|
||||
/// http://www.pinvoke.net/default.aspx/Enums.CREDUI_FLAGS
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/dpapiusercredentials.asp
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
|
||||
/// </summary>
|
||||
[Flags] public enum FLAGS {
|
||||
INCORRECT_PASSWORD = 0x1,
|
||||
DO_NOT_PERSIST = 0x2,
|
||||
REQUEST_ADMINISTRATOR = 0x4,
|
||||
EXCLUDE_CERTIFICATES = 0x8,
|
||||
REQUIRE_CERTIFICATE = 0x10,
|
||||
SHOW_SAVE_CHECK_BOX = 0x40,
|
||||
ALWAYS_SHOW_UI = 0x80,
|
||||
REQUIRE_SMARTCARD = 0x100,
|
||||
PASSWORD_ONLY_OK = 0x200,
|
||||
VALIDATE_USERNAME = 0x400,
|
||||
COMPLETE_USERNAME = 0x800,
|
||||
PERSIST = 0x1000,
|
||||
SERVER_CREDENTIAL = 0x4000,
|
||||
EXPECT_CONFIRMATION = 0x20000,
|
||||
GENERIC_CREDENTIALS = 0x40000,
|
||||
USERNAME_TARGET_CREDENTIALS = 0x80000,
|
||||
KEEP_USERNAME = 0x100000,
|
||||
}
|
||||
|
||||
/// <summary>http://www.pinvoke.net/default.aspx/Enums.CredUIReturnCodes</summary>
|
||||
public enum ReturnCodes {
|
||||
NO_ERROR = 0,
|
||||
ERROR_INVALID_PARAMETER = 87,
|
||||
ERROR_INSUFFICIENT_BUFFER = 122,
|
||||
ERROR_INVALID_FLAGS = 1004,
|
||||
ERROR_NOT_FOUND = 1168,
|
||||
ERROR_CANCELLED = 1223,
|
||||
ERROR_NO_SUCH_LOGON_SESSION = 1312,
|
||||
ERROR_INVALID_ACCOUNT_NAME = 1315
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// http://www.pinvoke.net/default.aspx/Structures.CREDUI_INFO
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/credui_info.asp
|
||||
/// </summary>
|
||||
public struct INFO {
|
||||
public int cbSize;
|
||||
public IntPtr hwndParent;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] public string pszMessageText;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] public string pszCaptionText;
|
||||
public IntPtr hbmBanner;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
|
||||
/// </summary>
|
||||
[DllImport("credui", EntryPoint="CredUIPromptForCredentialsW", CharSet=CharSet.Unicode)]
|
||||
public static extern ReturnCodes PromptForCredentials(
|
||||
ref INFO creditUR,
|
||||
string targetName,
|
||||
IntPtr reserved1,
|
||||
int iError,
|
||||
StringBuilder userName,
|
||||
int maxUserName,
|
||||
StringBuilder password,
|
||||
int maxPassword,
|
||||
ref int iSave,
|
||||
FLAGS flags
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// http://www.pinvoke.net/default.aspx/credui.CredUIConfirmCredentials
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduiconfirmcredentials.asp
|
||||
/// </summary>
|
||||
[DllImport("credui.dll", EntryPoint="CredUIConfirmCredentialsW", CharSet=CharSet.Unicode)]
|
||||
public static extern ReturnCodes ConfirmCredentials(string targetName, bool confirm);
|
||||
}
|
||||
}
|
47
GreenshotPlugin/Core/GreenshotResources.cs
Normal file
47
GreenshotPlugin/Core/GreenshotResources.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// Centralized storage of the icons & bitmaps
|
||||
/// </summary>
|
||||
public class GreenshotResources {
|
||||
private static ComponentResourceManager greenshotResources = new ComponentResourceManager(typeof(GreenshotResources));
|
||||
|
||||
public static Image getImage(string imageName) {
|
||||
return (Image)greenshotResources.GetObject(imageName);
|
||||
}
|
||||
public static Icon getIcon(string imageName) {
|
||||
return (Icon)greenshotResources.GetObject(imageName);
|
||||
}
|
||||
|
||||
public static Icon getGreenshotIcon() {
|
||||
return getIcon("Greenshot.Icon");
|
||||
}
|
||||
|
||||
public static Image getGreenshotImage() {
|
||||
return getImage("Greenshot.Image");
|
||||
}
|
||||
}
|
||||
}
|
459
GreenshotPlugin/Core/GreenshotResources.resx
Normal file
459
GreenshotPlugin/Core/GreenshotResources.resx
Normal file
|
@ -0,0 +1,459 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="Greenshot.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
|
||||
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
|
||||
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
|
||||
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
|
||||
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
|
||||
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
|
||||
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
|
||||
AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4
|
||||
TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq
|
||||
d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg
|
||||
lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR
|
||||
xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB
|
||||
+ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE
|
||||
UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU
|
||||
LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA
|
||||
AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/
|
||||
//8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/
|
||||
9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/
|
||||
0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/
|
||||
l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/
|
||||
cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/
|
||||
UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy
|
||||
Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ
|
||||
Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs
|
||||
APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA
|
||||
AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA
|
||||
AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA
|
||||
Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA
|
||||
JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA
|
||||
AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS
|
||||
REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA
|
||||
ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W
|
||||
ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw
|
||||
CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+
|
||||
FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB
|
||||
AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1
|
||||
VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk
|
||||
iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV
|
||||
uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE
|
||||
7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA
|
||||
kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG
|
||||
cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi
|
||||
UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm
|
||||
LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA
|
||||
AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/
|
||||
//8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/
|
||||
5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/
|
||||
trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/
|
||||
kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/
|
||||
cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0
|
||||
Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm
|
||||
Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+
|
||||
Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR
|
||||
LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn
|
||||
OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD
|
||||
AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA
|
||||
AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka
|
||||
AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO
|
||||
OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo
|
||||
DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy
|
||||
XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg
|
||||
mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL
|
||||
2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA
|
||||
z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA
|
||||
sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI
|
||||
kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw
|
||||
cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA
|
||||
UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv
|
||||
JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA
|
||||
AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/
|
||||
//8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/
|
||||
1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/
|
||||
scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/
|
||||
kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2
|
||||
cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0
|
||||
Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY
|
||||
Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV
|
||||
AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA
|
||||
AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF
|
||||
JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
</value>
|
||||
</data>
|
||||
<data name="Greenshot.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
52
GreenshotPlugin/Core/IEHelper.cs
Normal file
52
GreenshotPlugin/Core/IEHelper.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// Description of IEHelper.
|
||||
/// </summary>
|
||||
public class IEHelper {
|
||||
// Internet explorer Registry key
|
||||
private const string IE_KEY = @"Software\Microsoft\Internet Explorer";
|
||||
/// <summary>
|
||||
/// Helper method to get the IE version
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int IEVersion() {
|
||||
int version = 7;
|
||||
// Seeing if IE 9 is used, here we need another offset!
|
||||
using (RegistryKey ieKey = Registry.LocalMachine.OpenSubKey(IE_KEY, false)) {
|
||||
if (ieKey != null) {
|
||||
object versionKey = ieKey.GetValue("Version");
|
||||
if (versionKey != null) {
|
||||
int.TryParse(versionKey.ToString().Substring(0,1), out version);
|
||||
}
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
private IEHelper() {
|
||||
}
|
||||
}
|
||||
}
|
496
GreenshotPlugin/Core/LanguageHelper.cs
Normal file
496
GreenshotPlugin/Core/LanguageHelper.cs
Normal file
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.Xml;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
|
||||
public interface ILanguage {
|
||||
void Load();
|
||||
string GetString(Enum id);
|
||||
string GetFormattedString(Enum id, object param);
|
||||
string GetHelpFilePath();
|
||||
|
||||
/// <summary>
|
||||
/// Set language
|
||||
/// </summary>
|
||||
/// <param name="wantedIETF">wanted IETF</param>
|
||||
/// <returns>Actuall IETF </returns>
|
||||
string SetLanguage(string cultureInfo);
|
||||
void SynchronizeLanguageToCulture();
|
||||
string CurrentLanguage {
|
||||
get;
|
||||
}
|
||||
|
||||
List<LanguageConfiguration> SupportedLanguages {
|
||||
get;
|
||||
}
|
||||
|
||||
String LanguageFilePattern {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
LanguageConfiguration CurrentLanguageConfiguration {
|
||||
get;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Description of Language.
|
||||
/// </summary>
|
||||
public class LanguageContainer : ILanguage {
|
||||
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(LanguageContainer));
|
||||
private static char [] TRIMCHARS = new char[] {' ', '\t', '\n', '\r'};
|
||||
private const string DEFAULT_LANGUAGE= "en-US";
|
||||
private static string APPLICATIONDATA_LANGUAGE_PATH = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),@"Greenshot\Languages\");
|
||||
private static string STARTUP_LANGUAGE_PATH = Path.Combine(Application.StartupPath, @"Languages\");
|
||||
private const string HELP_FILENAME_PATTERN = @"help-*.html";
|
||||
|
||||
private Dictionary<string, string> strings = new Dictionary<string, string>();
|
||||
private List<LanguageConfiguration> languages = new List<LanguageConfiguration>();
|
||||
private string currentIETF = null;
|
||||
private string languageFilePattern;
|
||||
|
||||
public LanguageContainer() {
|
||||
}
|
||||
|
||||
public String LanguageFilePattern {
|
||||
get {
|
||||
return languageFilePattern;
|
||||
}
|
||||
set {
|
||||
languageFilePattern = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Load() {
|
||||
languages = LoadFiles(languageFilePattern);
|
||||
}
|
||||
|
||||
public string CurrentLanguage {
|
||||
get {
|
||||
return currentIETF;
|
||||
}
|
||||
}
|
||||
|
||||
public List<LanguageConfiguration> SupportedLanguages {
|
||||
get {
|
||||
return languages;
|
||||
}
|
||||
}
|
||||
|
||||
public LanguageConfiguration CurrentLanguageConfiguration {
|
||||
get {
|
||||
foreach(LanguageConfiguration languageConfiguration in SupportedLanguages) {
|
||||
if (currentIETF.Equals(languageConfiguration.Ietf)) {
|
||||
return languageConfiguration;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SynchronizeLanguageToCulture() {
|
||||
if (CurrentLanguage == null || !CurrentLanguage.Equals(Thread.CurrentThread.CurrentUICulture.Name)) {
|
||||
SetLanguage(Thread.CurrentThread.CurrentUICulture.Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set language
|
||||
/// </summary>
|
||||
/// <param name="wantedIETF">wanted IETF</param>
|
||||
/// <returns>Actuall IETF </returns>
|
||||
public string SetLanguage(string wantedIETF) {
|
||||
LOG.Debug("SetLanguage called for : " + wantedIETF);
|
||||
Dictionary<string, LanguageConfiguration> identifiedLanguages = new Dictionary<string, LanguageConfiguration>();
|
||||
|
||||
if (languages == null || languages.Count == 0) {
|
||||
throw new FileNotFoundException("No language files found!");
|
||||
}
|
||||
|
||||
// Find selected languages in available languages
|
||||
foreach(LanguageConfiguration language in languages) {
|
||||
LOG.Debug("Found language: " + language.Ietf);
|
||||
identifiedLanguages.Add(language.Ietf, language);
|
||||
}
|
||||
|
||||
LanguageConfiguration selectedLanguage = null;
|
||||
try {
|
||||
selectedLanguage = identifiedLanguages[wantedIETF];
|
||||
} catch (KeyNotFoundException) {
|
||||
LOG.Warn("Selecteded language " + wantedIETF + " not found.");
|
||||
}
|
||||
|
||||
// Make best match for language (e.g. en -> "en-US")
|
||||
if (selectedLanguage == null) {
|
||||
foreach(string ietf in identifiedLanguages.Keys) {
|
||||
if (ietf.StartsWith(wantedIETF)) {
|
||||
try {
|
||||
selectedLanguage = identifiedLanguages[ietf];
|
||||
LOG.Info("Selecteded language " + ietf + " by near match for: " + wantedIETF);
|
||||
wantedIETF = ietf;
|
||||
break;
|
||||
} catch (KeyNotFoundException) {
|
||||
LOG.Warn("Selecteded language " + wantedIETF + " not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedLanguage == null && !DEFAULT_LANGUAGE.Equals(wantedIETF)) {
|
||||
try {
|
||||
selectedLanguage = identifiedLanguages[DEFAULT_LANGUAGE];
|
||||
} catch (KeyNotFoundException) {
|
||||
LOG.Warn("No english language file found!!");
|
||||
}
|
||||
}
|
||||
if (selectedLanguage == null) {
|
||||
// Select first (maybe only) language!
|
||||
selectedLanguage = languages[0];
|
||||
LOG.Warn("Selected " + selectedLanguage.Ietf + " as fallback language!");
|
||||
}
|
||||
|
||||
// build directionary for the strings
|
||||
strings.Clear();
|
||||
foreach(Resource resource in selectedLanguage.Resources) {
|
||||
AddResource(resource);
|
||||
}
|
||||
|
||||
currentIETF = selectedLanguage.Ietf;
|
||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo(currentIETF);
|
||||
|
||||
return currentIETF;
|
||||
}
|
||||
|
||||
private void AddResource(Resource resource) {
|
||||
try {
|
||||
if (resource.Text != null) {
|
||||
strings.Add(resource.Name, resource.Text.Trim(TRIMCHARS));
|
||||
} else {
|
||||
LOG.Warn("Resource is null: " + resource.Name);
|
||||
strings.Add(resource.Name, "");
|
||||
}
|
||||
} catch (ArgumentException ae) {
|
||||
LOG.Error("Problem adding " + resource.Name, ae);
|
||||
throw ae;
|
||||
}
|
||||
}
|
||||
|
||||
private List<LanguageConfiguration> LoadFiles(string languageFilePattern) {
|
||||
List<LanguageConfiguration> loadedLanguages = new List<LanguageConfiguration>();
|
||||
List<string> languageDirectories = new List<string>();
|
||||
languageDirectories.Add(STARTUP_LANGUAGE_PATH);
|
||||
languageDirectories.Add(APPLICATIONDATA_LANGUAGE_PATH);
|
||||
foreach(string path in languageDirectories) {
|
||||
// Search in executable directory
|
||||
if (Directory.Exists(path)) {
|
||||
foreach(string languageFile in Directory.GetFiles(path, languageFilePattern, SearchOption.AllDirectories)) {
|
||||
LanguageConfiguration languageConfig = LanguageConfiguration.Load(languageFile);
|
||||
if (languageConfig != null) {
|
||||
LOG.Info("Loaded language: " + languageConfig.Description);
|
||||
loadedLanguages.Add(languageConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return loadedLanguages;
|
||||
}
|
||||
|
||||
public void Validate(Enum languageKeys) {
|
||||
Dictionary<string, List<string>> keysPerLanguage = new Dictionary<string, List<string>>();
|
||||
foreach(LanguageConfiguration languageToValidate in languages) {
|
||||
List<string> keys = new List<string>();
|
||||
foreach(Resource resource in languageToValidate.Resources) {
|
||||
keys.Add(resource.Name);
|
||||
}
|
||||
keys.Sort();
|
||||
keysPerLanguage.Add(languageToValidate.Ietf, keys);
|
||||
}
|
||||
|
||||
// Make list of values in the enum
|
||||
List<string> fixedKeys = new List<string>();
|
||||
foreach(Enum langKey in Enum.GetValues(languageKeys.GetType())) {
|
||||
fixedKeys.Add(langKey.ToString());
|
||||
}
|
||||
|
||||
foreach(string ietf in keysPerLanguage.Keys) {
|
||||
List<string> keys = keysPerLanguage[ietf];
|
||||
foreach(string key in fixedKeys) {
|
||||
if (!keys.Contains(key)) {
|
||||
LOG.Warn(ietf + " is missing resource with name [" + key + "]");
|
||||
}
|
||||
}
|
||||
foreach(string key in keys) {
|
||||
if (!fixedKeys.Contains(key)) {
|
||||
LOG.Warn(ietf + " has additional resource with name [" + key + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ToEnum() {
|
||||
if (!LOG.IsDebugEnabled) {
|
||||
return;
|
||||
}
|
||||
StringBuilder EnumClass = new StringBuilder();
|
||||
EnumClass.AppendLine("/*");
|
||||
EnumClass.AppendLine(" * Auto generated");
|
||||
EnumClass.AppendLine(" */");
|
||||
EnumClass.AppendLine("using System;");
|
||||
EnumClass.AppendLine();
|
||||
EnumClass.AppendLine("namespace Greenshot.Configuration {");
|
||||
EnumClass.AppendLine(" public enum LangKey {");
|
||||
|
||||
List<string> keys = new List<string>();
|
||||
foreach(LanguageConfiguration foundLanguage in languages) {
|
||||
if (foundLanguage.Ietf.Equals(DEFAULT_LANGUAGE)) {
|
||||
foreach(Resource resource in foundLanguage.Resources) {
|
||||
keys.Add(resource.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
keys.Sort();
|
||||
bool added = false;
|
||||
foreach(string key in keys) {
|
||||
if (added) {
|
||||
EnumClass.AppendLine(",");
|
||||
}
|
||||
EnumClass.Append(" " + key);
|
||||
added = true;
|
||||
}
|
||||
EnumClass.AppendLine();
|
||||
EnumClass.AppendLine(" }");
|
||||
EnumClass.AppendLine("}");
|
||||
LOG.Debug("LangKeys should be: \r\n" + EnumClass.ToString());
|
||||
}
|
||||
|
||||
public string GetString(Enum id) {
|
||||
if(!strings.ContainsKey(id.ToString())) {
|
||||
AdoptMissingResourcesFromDefaultLanguage();
|
||||
}
|
||||
try {
|
||||
return strings[id.ToString()];
|
||||
} catch (KeyNotFoundException) {
|
||||
return "string ###"+id+"### not found";
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFormattedString(Enum id, object param) {
|
||||
if(!strings.ContainsKey(id.ToString())) {
|
||||
AdoptMissingResourcesFromDefaultLanguage();
|
||||
}
|
||||
try {
|
||||
return String.Format(strings[id.ToString()], param);
|
||||
} catch (KeyNotFoundException) {
|
||||
return "string ###"+id+"### not found";
|
||||
}
|
||||
}
|
||||
|
||||
private void AdoptMissingResourcesFromDefaultLanguage() {
|
||||
LanguageConfiguration defaultLanguageConfiguration = GetDefaultLanguageConfiguration();
|
||||
if (defaultLanguageConfiguration != null) {
|
||||
foreach(Resource resource in defaultLanguageConfiguration.Resources) {
|
||||
if(resource != null && !strings.ContainsKey(resource.Name)) {
|
||||
AddResource(resource);
|
||||
if(LOG.IsWarnEnabled) {
|
||||
LOG.Warn("Adopted missing string resource from default language: "+resource.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG.Warn("Default language file is missing! The default language file is: " + DEFAULT_LANGUAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private LanguageConfiguration GetDefaultLanguageConfiguration() {
|
||||
foreach(LanguageConfiguration language in languages) {
|
||||
if(language.Ietf == DEFAULT_LANGUAGE) return language;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// finds a returns the path of the best matching help file.
|
||||
/// 1st tries to find file for currentLanguage, 2nd for defaultLanguage.
|
||||
/// if neither is found, the first help file found is returned
|
||||
public string GetHelpFilePath() {
|
||||
List<string> helpFiles = new List<string>();
|
||||
// Search in executable directory
|
||||
if (Directory.Exists(STARTUP_LANGUAGE_PATH)) {
|
||||
helpFiles.AddRange(Directory.GetFiles(STARTUP_LANGUAGE_PATH, HELP_FILENAME_PATTERN, SearchOption.AllDirectories));
|
||||
}
|
||||
// Search in ApplicationData directory
|
||||
if (Directory.Exists(APPLICATIONDATA_LANGUAGE_PATH)) {
|
||||
helpFiles.AddRange(Directory.GetFiles(APPLICATIONDATA_LANGUAGE_PATH, HELP_FILENAME_PATTERN, SearchOption.AllDirectories));
|
||||
}
|
||||
|
||||
foreach(string helpFile in helpFiles) {
|
||||
if(helpFile.EndsWith(currentIETF+".html")) {
|
||||
return helpFile;
|
||||
}
|
||||
}
|
||||
foreach(string helpFile in helpFiles) {
|
||||
if(helpFile.EndsWith(DEFAULT_LANGUAGE+".html")) {
|
||||
return helpFile;
|
||||
}
|
||||
}
|
||||
LOG.Warn("Help file not found for default language, will load "+helpFiles[0]);
|
||||
return helpFiles[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LanguageConfiguration {
|
||||
|
||||
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(LanguageConfiguration));
|
||||
|
||||
public string description;
|
||||
public string Description {
|
||||
get {
|
||||
return description;
|
||||
}
|
||||
set {
|
||||
description = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ietf;
|
||||
public string Ietf {
|
||||
get {
|
||||
return ietf;
|
||||
}
|
||||
set {
|
||||
ietf = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string version;
|
||||
public string Version {
|
||||
get {
|
||||
return version;
|
||||
}
|
||||
set {
|
||||
version = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string file;
|
||||
public string File {
|
||||
get {
|
||||
return file;
|
||||
}
|
||||
set {
|
||||
file = value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Resource> Resources;
|
||||
|
||||
public LanguageConfiguration() {
|
||||
Resources = new List<Resource>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// loads a language configuration from a file path
|
||||
/// </summary>
|
||||
public static LanguageConfiguration Load(string path) {
|
||||
LanguageConfiguration ret = null;
|
||||
try {
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(path);
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("language");
|
||||
if(nodes.Count > 0) {
|
||||
ret = new LanguageConfiguration();
|
||||
ret.File = path;
|
||||
XmlNode node = nodes.Item(0);
|
||||
ret.Description = node.Attributes["description"].Value;
|
||||
ret.Ietf = node.Attributes["ietf"].Value;
|
||||
ret.Version = node.Attributes["version"].Value;
|
||||
|
||||
XmlNodeList resourceNodes = doc.GetElementsByTagName("resource");
|
||||
ret.Resources = new List<Resource>(resourceNodes.Count);
|
||||
foreach(XmlNode resourceNode in resourceNodes) {
|
||||
Resource res = new Resource();
|
||||
res.Name = resourceNode.Attributes["name"].Value;
|
||||
res.Text = resourceNode.InnerText;
|
||||
ret.Resources.Add(res);
|
||||
}
|
||||
} else {
|
||||
throw new XmlException("Root element <language> is missing");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
LOG.Error("Could not load language file "+path, e);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class Resource {
|
||||
|
||||
public string name;
|
||||
public string Name {get; set;}
|
||||
|
||||
public string text;
|
||||
public string Text {get; set;}
|
||||
|
||||
public override int GetHashCode() {
|
||||
int hash = 7;
|
||||
if (Text != null) {
|
||||
hash = hash ^ Text.GetHashCode();
|
||||
}
|
||||
if (Name != null) {
|
||||
hash = hash ^ Name.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj is Resource) {
|
||||
Resource other = (Resource) obj;
|
||||
if(Name == null) {
|
||||
if (other.Name != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(Text == null) {
|
||||
if (other.Text != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return (Name.Equals(other.Name) && Text.Equals(other.Text));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
133
GreenshotPlugin/Core/NetworkHelper.cs
Normal file
133
GreenshotPlugin/Core/NetworkHelper.cs
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// Description of NetworkHelper.
|
||||
/// </summary>
|
||||
public class NetworkHelper {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(NetworkHelper));
|
||||
private static CoreConfiguration config = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
|
||||
/// <summary>
|
||||
/// Download a file as string
|
||||
/// </summary>
|
||||
/// <param name=url">An Uri to specify the download location</param>
|
||||
/// <param name=encoding">The encoding to use</param>
|
||||
/// <returns>string with the file content</returns>
|
||||
public static string DownloadFileAsString(Uri url, Encoding encoding) {
|
||||
try {
|
||||
HttpWebRequest request = (HttpWebRequest)CreatedWebRequest(url);
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (request.HaveResponse) {
|
||||
StreamReader reader = new StreamReader(response.GetResponseStream(), encoding);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.Error("Problem downloading from: " + url.ToString(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the FavIcon as a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="baseUri"></param>
|
||||
/// <returns>Bitmap with the FavIcon</returns>
|
||||
public static Bitmap DownloadFavIcon(Uri baseUri) {
|
||||
Uri url = new Uri(baseUri, new Uri("favicon.ico"));
|
||||
try {
|
||||
HttpWebRequest request = (HttpWebRequest)NetworkHelper.CreatedWebRequest(url);
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (request.HaveResponse) {
|
||||
Image image = Image.FromStream(response.GetResponseStream());
|
||||
return (image.Height > 16 && image.Width > 16) ? new Bitmap(image, 16, 16) : new Bitmap(image);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.Error("Problem downloading the FavIcon from: " + baseUri.ToString(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request, eventually with proxy
|
||||
/// </summary>
|
||||
/// <param name="uri">string with uri to connect to</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static WebRequest CreatedWebRequest(string uri) {
|
||||
return CreatedWebRequest(new Uri(uri));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request, eventually with proxy
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri with uri to connect to</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static WebRequest CreatedWebRequest(Uri uri) {
|
||||
WebRequest webRequest = WebRequest.Create(uri);
|
||||
if (config.UseProxy) {
|
||||
webRequest.Proxy = GreenshotPlugin.Core.NetworkHelper.CreateProxy(uri);
|
||||
//webRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
|
||||
}
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a IWebProxy Object which can be used to access the Internet
|
||||
/// This method will check the configuration if the proxy is allowed to be used.
|
||||
/// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns>
|
||||
public static IWebProxy CreateProxy(Uri uri) {
|
||||
IWebProxy proxyToUse = null;
|
||||
if (config.UseProxy) {
|
||||
proxyToUse = WebRequest.DefaultWebProxy;
|
||||
if (proxyToUse != null) {
|
||||
proxyToUse.Credentials = CredentialCache.DefaultCredentials;
|
||||
if (LOG.IsDebugEnabled) {
|
||||
// check the proxy for the Uri
|
||||
if (!proxyToUse.IsBypassed(uri)) {
|
||||
Uri proxyUri = proxyToUse.GetProxy(uri);
|
||||
if (proxyUri != null) {
|
||||
LOG.Debug("Using proxy: " + proxyUri.ToString() + " for " + uri.ToString());
|
||||
} else {
|
||||
LOG.Debug("No proxy found!");
|
||||
}
|
||||
} else {
|
||||
LOG.Debug("Proxy bypass for: " + uri.ToString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG.Debug("No proxy found!");
|
||||
}
|
||||
}
|
||||
return proxyToUse;
|
||||
}
|
||||
}
|
||||
}
|
73
GreenshotPlugin/Core/PluginUtils.cs
Normal file
73
GreenshotPlugin/Core/PluginUtils.cs
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Greenshot.Plugin;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// Description of PluginUtils.
|
||||
/// </summary>
|
||||
public class PluginUtils {
|
||||
private PluginUtils() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToFileMenu(IImageEditor imageEditor, ToolStripMenuItem item) {
|
||||
ToolStripMenuItem toolStripMenuItem = imageEditor.GetFileMenuItem();
|
||||
bool added = false;
|
||||
for(int i = 0; i< toolStripMenuItem.DropDownItems.Count; i++) {
|
||||
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) {
|
||||
toolStripMenuItem.DropDownItems.Insert(i, item);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
toolStripMenuItem.DropDownItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToPluginMenu(IImageEditor imageEditor, ToolStripMenuItem item) {
|
||||
ToolStripMenuItem toolStripMenuItem = imageEditor.GetPluginMenuItem();
|
||||
bool added = false;
|
||||
for(int i = 0; i< toolStripMenuItem.DropDownItems.Count; i++) {
|
||||
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) {
|
||||
toolStripMenuItem.DropDownItems.Insert(i, item);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
toolStripMenuItem.DropDownItems.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
GreenshotPlugin/Core/PropertyHelper.cs
Normal file
124
GreenshotPlugin/Core/PropertyHelper.cs
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
/// A Class to representate a simple "java" properties file
|
||||
/// </summary>
|
||||
public class Properties : Dictionary<string, string >{
|
||||
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(Properties));
|
||||
|
||||
public string GetProperty(string key) {
|
||||
try {
|
||||
return this[key];
|
||||
} catch (KeyNotFoundException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Split property with ',' and return the splitted string as a string[]
|
||||
/// </summary>
|
||||
public string[] GetPropertyAsArray(string key) {
|
||||
try {
|
||||
string array = this[key];
|
||||
return array.Split(new Char[] {','});
|
||||
} catch (KeyNotFoundException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public bool GetBoolProperty(string key) {
|
||||
if (this.ContainsKey(key)) {
|
||||
return bool.Parse(this[key]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public uint GetUIntProperty(string key) {
|
||||
return uint.Parse(this[key]);
|
||||
}
|
||||
public int GetIntProperty(string key) {
|
||||
return int.Parse(this[key]);
|
||||
}
|
||||
public void AddProperty(string key, string value) {
|
||||
Add(key, value);
|
||||
}
|
||||
public void AddBoolProperty(string key, bool value) {
|
||||
AddProperty(key, value.ToString());
|
||||
}
|
||||
public void ChangeProperty(string key, string value) {
|
||||
if (this.ContainsKey(key)) {
|
||||
this[key] = value;
|
||||
} else {
|
||||
throw new KeyNotFoundException(key);
|
||||
}
|
||||
}
|
||||
public void ChangeBoolProperty(string key, bool value) {
|
||||
ChangeProperty(key, value.ToString());
|
||||
}
|
||||
|
||||
public void write(string filename) {
|
||||
using ( TextWriter textWriter = new StreamWriter(filename)) {
|
||||
foreach(string key in Keys) {
|
||||
textWriter.WriteLine(key +"=" + this[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(string filename, string header) {
|
||||
using ( TextWriter textWriter = new StreamWriter(filename)) {
|
||||
if (header != null) {
|
||||
textWriter.WriteLine(header);
|
||||
}
|
||||
foreach(string key in Keys) {
|
||||
textWriter.WriteLine(key +"=" + this[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read properties file
|
||||
public static Properties read(string filename) {
|
||||
LOG.Debug("Reading properties from file: " + filename);
|
||||
if (!File.Exists(filename)) {
|
||||
return null;
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
foreach (string line in File.ReadAllLines(filename)) {
|
||||
if (line == null) {
|
||||
continue;
|
||||
}
|
||||
string currentLine = line.Trim();
|
||||
if (!currentLine.StartsWith("#") && currentLine.IndexOf('=') > 0) {
|
||||
string [] split = currentLine.Split(new Char[] {'='}, 2);
|
||||
if (split != null && split.Length == 2) {
|
||||
string name = split[0];
|
||||
if (name == null || name.Length < 1) {
|
||||
continue;
|
||||
}
|
||||
properties.Add(name.Trim(), split[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue