mit hyphen
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Helpers
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class EnumValueFriendlyNameAttribute : Attribute
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private string friendlyName;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public EnumValueFriendlyNameAttribute(string name)
|
||||
{
|
||||
this.friendlyName = name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public string FriendlyName
|
||||
{
|
||||
get { return friendlyName; }
|
||||
set { friendlyName = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static Dictionary<TEnum, string> GetFriendlyNames<TEnum>() where TEnum : struct
|
||||
{
|
||||
Type enumType = typeof(TEnum);
|
||||
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("TEnum is not an enumeration.", "TEnum");
|
||||
|
||||
Type thisType = typeof(EnumValueFriendlyNameAttribute);
|
||||
Dictionary<TEnum, string> results = new Dictionary<TEnum, string>(1);
|
||||
|
||||
foreach (FieldInfo field in enumType.GetFields())
|
||||
{
|
||||
if ((field.Attributes & FieldAttributes.Literal) != FieldAttributes.Literal)
|
||||
continue;
|
||||
|
||||
EnumValueFriendlyNameAttribute[] names = (EnumValueFriendlyNameAttribute[])field.GetCustomAttributes(thisType, false);
|
||||
|
||||
if (names != null && names.Length > 0)
|
||||
results.Add((TEnum)field.GetRawConstantValue(), names[0].FriendlyName);
|
||||
else
|
||||
results.Add((TEnum)field.GetRawConstantValue(), field.Name);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,652 @@
|
||||
/* /--==###################==--\
|
||||
* | Bram's Ini File Handler |
|
||||
* \--==###################==--/
|
||||
*
|
||||
* This handles Ini files and all their content.
|
||||
*
|
||||
* Some explanation:
|
||||
* Categories are in fact sections, but i didn't think
|
||||
* "sections" so i wrote "categories". Sorry.
|
||||
*
|
||||
* comment lines in ini files begin with #, ; or //
|
||||
* multi-line are not supported (Because I've never seen such)
|
||||
*
|
||||
* It ignores comments on reading but can write them
|
||||
*
|
||||
* How it works:
|
||||
* All data is saved in one System.Collections.SortedList which
|
||||
* contains the category names as keys, and all key-value pairs
|
||||
* as values, saved as SortedList too:
|
||||
*
|
||||
* explanation sheet
|
||||
*
|
||||
* SortedList Categories
|
||||
* {
|
||||
* {"Category1", {Key1, value1}
|
||||
* {Key2, value2}
|
||||
* ...
|
||||
* }
|
||||
* {"Category2", {Key1, value1}
|
||||
* {Key2, value2}
|
||||
* ...
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* that behaves like an array in an array (array[][]), but with dynamic bounds
|
||||
* and strings as indexers.
|
||||
*
|
||||
* I hope you did understand this, it would have been easier to explain
|
||||
* in French or German...
|
||||
*
|
||||
* You can make with it what you want, but I would be pleased to
|
||||
* hear some feedback. (Ok, I admit: I would be pleased only if it's
|
||||
* positive feedback...)
|
||||
*
|
||||
* Send me an email! kratchkov@inbox.lv
|
||||
*
|
||||
* Thanks
|
||||
*
|
||||
* DISCLAIMER:
|
||||
* THIS CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
* KIND, EITHER EXPRESSED OR IMPLIED INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THIS
|
||||
* CODE IS WITH YOU. SHOULD THIS CODE PROVE DEFECTIVE, YOU ASSUME
|
||||
* THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION .
|
||||
* You take full responsibility for the use of this code and any
|
||||
* consequences thereof. I can not accept liability for damages
|
||||
* or failures arising from the use of this code, or parts of this code.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles Ini categories, keys and their associated values, static methods implemented for file
|
||||
/// handling (saving and reading)
|
||||
/// </summary>
|
||||
public class IniStructure
|
||||
{
|
||||
#region Ini structure code
|
||||
private SortedList Categories = new SortedList();
|
||||
|
||||
/// <summary>
|
||||
/// Initialies a new IniStructure
|
||||
/// </summary>
|
||||
public IniStructure()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a category to the IniStructure
|
||||
/// </summary>
|
||||
/// <param name="Name">Name of the new category</param>
|
||||
public bool AddCategory(string Name)
|
||||
{
|
||||
if (Name == "" | Categories.ContainsKey(Name))
|
||||
return false;
|
||||
if (Name.IndexOf('=') != -1
|
||||
| Name.IndexOf('[') != -1
|
||||
| Name.IndexOf(']') != -1) // these characters are not allowed in a category name
|
||||
return false;
|
||||
|
||||
Categories.Add(Name, new SortedList());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a category and its contents
|
||||
/// </summary>
|
||||
/// <param name="Name">category to delete</param>
|
||||
public bool DeleteCategory(string Name)
|
||||
{
|
||||
if (Name == "" | !Categories.ContainsKey(Name))
|
||||
return false;
|
||||
Categories.Remove(Name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames a category
|
||||
/// </summary>
|
||||
/// <param name="Name">Category to rename</param>
|
||||
/// <param name="NewName">New name</param>
|
||||
public bool RenameCategory(string Name, string NewName)
|
||||
{ // Or rather moves a category to a new name
|
||||
if (Name == "" | !Categories.ContainsKey(Name) | NewName == "")
|
||||
return false;
|
||||
|
||||
if (NewName.IndexOf('=') != -1
|
||||
| NewName.IndexOf('[') != -1
|
||||
| NewName.IndexOf(']') != -1) // these characters are not allowed in a category name
|
||||
return false;
|
||||
|
||||
SortedList Category = (SortedList)(Categories[Name]);
|
||||
Categories.Add(NewName, Category);
|
||||
this.DeleteCategory(Name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the names of all categories
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string[] GetCategories()
|
||||
{
|
||||
string[] CatNames = new string[Categories.Count];
|
||||
IList KeyList = Categories.GetKeyList();
|
||||
int KeyCount = Categories.Count;
|
||||
for (int i = 0; i < KeyCount; i++)
|
||||
{
|
||||
CatNames[i] = KeyList[i].ToString();
|
||||
}
|
||||
return CatNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of a category by specifying the index.
|
||||
/// Useful to enumerate through all categories.
|
||||
/// </summary>
|
||||
/// <param name="Index">The category index</param>
|
||||
/// <returns></returns>
|
||||
public string GetCategoryName(int Index)
|
||||
{
|
||||
if (Index < 0 | Index >= Categories.Count)
|
||||
return null;
|
||||
return Categories.GetKey(Index).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a key-value pair to a specified category
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Name of the category</param>
|
||||
/// <param name="Key">New name of the key</param>
|
||||
/// <param name="Value">Associated value</param>
|
||||
public bool AddValue(string CategoryName, string Key, string Value)
|
||||
{
|
||||
if (CategoryName == "" | Key == "")
|
||||
return false;
|
||||
if (Key.IndexOf('=') != -1
|
||||
| Key.IndexOf('[') != -1
|
||||
| Key.IndexOf(']') != -1 // these chars are not allowed for keynames
|
||||
| Key.IndexOf(';') != -1
|
||||
| Key.IndexOf('#') != -1
|
||||
)
|
||||
return false;
|
||||
if (!Categories.ContainsKey(CategoryName))
|
||||
return false;
|
||||
SortedList Category = (SortedList)(Categories[CategoryName]);
|
||||
if (Category.ContainsKey(Key))
|
||||
return false;
|
||||
Category.Add(Key, Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value of a key-value pair in a specified category by specifying the key
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Name of the category</param>
|
||||
/// <param name="Key">Name of the Key</param>
|
||||
/// <returns></returns>
|
||||
public string GetValue(string CategoryName, string Key)
|
||||
{
|
||||
if (CategoryName == "" | Key == "")
|
||||
return null;
|
||||
if (!Categories.ContainsKey(CategoryName))
|
||||
return null;
|
||||
SortedList Category = (SortedList)(Categories[CategoryName]);
|
||||
if (!Category.ContainsKey(Key))
|
||||
return null;
|
||||
return Category[Key].ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the key-value pair in a specified category by specifying the index
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Index of the category</param>
|
||||
/// <param name="Key">Index of the Key</param>
|
||||
/// <returns></returns>
|
||||
public string GetValue(int CatIndex, int KeyIndex)
|
||||
{
|
||||
if (CatIndex < 0 | KeyIndex < 0
|
||||
|CatIndex >= Categories.Count)
|
||||
return null;
|
||||
SortedList Category = (SortedList)(Categories.GetByIndex(CatIndex));
|
||||
if (KeyIndex >= Category.Count)
|
||||
return null;
|
||||
return Category.GetByIndex(KeyIndex).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the key in a key-value pair in a specified category by specifying the index
|
||||
/// </summary>
|
||||
/// <param name="CatIndex">Index of the category</param>
|
||||
/// <param name="KeyIndex">Index of the key</param>
|
||||
/// <returns></returns>
|
||||
public string GetKeyName(int CatIndex, int KeyIndex)
|
||||
{
|
||||
if (CatIndex < 0 | KeyIndex < 0
|
||||
|CatIndex >= Categories.Count)
|
||||
return null;
|
||||
SortedList Category = (SortedList)(Categories.GetByIndex(CatIndex));
|
||||
if (KeyIndex >= Category.Count)
|
||||
return null;
|
||||
return Category.GetKey(KeyIndex).ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a key-value pair
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Name of the category</param>
|
||||
/// <param name="Key">Name of the Key</param>
|
||||
public bool DeleteValue(string CategoryName, string Key)
|
||||
{
|
||||
if (CategoryName == "" | Key == "")
|
||||
return false;
|
||||
if (!Categories.ContainsKey(CategoryName))
|
||||
return false;
|
||||
SortedList Category = (SortedList)(Categories[CategoryName]);
|
||||
if (!Category.ContainsKey(Key))
|
||||
return false;
|
||||
Category.Remove(Key);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames the keyname in a key-value pair
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Name of the category</param>
|
||||
/// <param name="KeyName">Name of the Key</param>
|
||||
/// <param name="NewKeyName">New name of the Key</param>
|
||||
public bool RenameKey(string CategoryName, string KeyName, string NewKeyName)
|
||||
{
|
||||
if (CategoryName == "" | KeyName == "" | NewKeyName == "")
|
||||
return false;
|
||||
if (!Categories.ContainsKey(CategoryName))
|
||||
return false;
|
||||
if (NewKeyName.IndexOf('=') != -1
|
||||
| NewKeyName.IndexOf('[') != -1
|
||||
| NewKeyName.IndexOf(']') != -1 // these chars are not allowed for keynames
|
||||
| NewKeyName.IndexOf(';') != -1
|
||||
| NewKeyName.IndexOf('#') != -1
|
||||
)
|
||||
return false;
|
||||
SortedList Category = (SortedList)(Categories[CategoryName]);
|
||||
if ( !Category.ContainsKey(KeyName))
|
||||
return false;
|
||||
|
||||
object value = Category[KeyName];
|
||||
Category.Remove(KeyName);
|
||||
Category.Add(NewKeyName, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the value in a key-value pair
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Name of the category</param>
|
||||
/// <param name="KeyName">Name of the Key</param>
|
||||
/// <param name="NewValue">New name of the Key</param>
|
||||
public bool ModifyValue(string CategoryName, string KeyName, string NewValue)
|
||||
{
|
||||
if (CategoryName == "" | KeyName == "")
|
||||
return false;
|
||||
if (!Categories.ContainsKey(CategoryName))
|
||||
return false;
|
||||
SortedList Category = (SortedList)(Categories[CategoryName]);
|
||||
if ( !Category.ContainsKey(KeyName))
|
||||
return false;
|
||||
|
||||
Category[KeyName] = NewValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all keys in a category
|
||||
/// </summary>
|
||||
/// <param name="CategoryName">Name of the category</param>
|
||||
/// <returns></returns>
|
||||
public string[] GetKeys(string CategoryName)
|
||||
{
|
||||
SortedList Category = (SortedList)(Categories[CategoryName]);
|
||||
if (Category == null)
|
||||
return new string[0];
|
||||
int KeyCount = Category.Count;
|
||||
string[] KeyNames = new string[KeyCount];
|
||||
IList KeyList = Category.GetKeyList();
|
||||
for (int i = 0; i < KeyCount; i++)
|
||||
{
|
||||
KeyNames[i] = KeyList[i].ToString();
|
||||
}
|
||||
return KeyNames;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ini writing code
|
||||
/// <summary>
|
||||
/// Writes an IniStructure to a file with a comment.
|
||||
/// </summary>
|
||||
/// <param name="IniData">The contents to write</param>
|
||||
/// <param name="Filename">The complete path and name of the file</param>
|
||||
/// <param name="comment">Comment to add</param>
|
||||
/// <returns></returns>
|
||||
public static bool WriteIni(IniStructure IniData, string Filename, string comment)
|
||||
{
|
||||
string DataToWrite = CreateData(IniData, BuildComment(comment));
|
||||
return WriteFile(Filename, DataToWrite);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an IniStructure to a file without a comment.
|
||||
/// </summary>
|
||||
/// <param name="IniData">The contents to write</param>
|
||||
/// <param name="Filename">The complete path and name of the file</param>
|
||||
/// <returns></returns>
|
||||
public static bool WriteIni(IniStructure IniData, string Filename)
|
||||
{
|
||||
string DataToWrite = CreateData(IniData);
|
||||
return WriteFile(Filename, DataToWrite);
|
||||
}
|
||||
|
||||
private static bool WriteFile(string Filename, string Data)
|
||||
{ // Writes a string to a file
|
||||
try
|
||||
{
|
||||
FileStream IniStream = new FileStream(Filename,FileMode.Create);
|
||||
if (!IniStream.CanWrite)
|
||||
{
|
||||
IniStream.Close();
|
||||
return false;
|
||||
}
|
||||
StreamWriter writer = new StreamWriter(IniStream);
|
||||
writer.Write(Data);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
IniStream.Close();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildComment(string comment)
|
||||
{ // Adds a # at the beginning of each line
|
||||
if (comment == "")
|
||||
return "";
|
||||
string[] Lines = DivideToLines(comment);
|
||||
string temp = "";
|
||||
foreach (string line in Lines)
|
||||
{
|
||||
temp += "# " + line + "\r\n";
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static string CreateData(IniStructure IniData)
|
||||
{
|
||||
return CreateData(IniData,"");
|
||||
}
|
||||
|
||||
private static string CreateData(IniStructure IniData, string comment)
|
||||
{ //Iterates through all categories and keys and appends all data to Data
|
||||
int CategoryCount = IniData.GetCategories().Length;
|
||||
int[] KeyCountPerCategory = new int[CategoryCount];
|
||||
string Data = comment;
|
||||
string[] temp = new string[2]; // will contain key-value pair
|
||||
|
||||
for (int i = 0; i < CategoryCount; i++) // Gets keycount per category
|
||||
{
|
||||
string CategoryName = IniData.GetCategories()[i];
|
||||
KeyCountPerCategory[i] = IniData.GetKeys(CategoryName).Length;
|
||||
}
|
||||
|
||||
for (int catcounter = 0; catcounter < CategoryCount; catcounter++)
|
||||
{
|
||||
Data += "\r\n[" + IniData.GetCategoryName(catcounter) + "]\r\n";
|
||||
// writes [Category] to Data
|
||||
for (int keycounter = 0; keycounter < KeyCountPerCategory[catcounter]; keycounter++)
|
||||
{
|
||||
temp[0] = IniData.GetKeyName(catcounter, keycounter);
|
||||
temp[1] = IniData.GetValue(catcounter, keycounter);
|
||||
Data += temp[0] + "=" + temp[1] + "\r\n";
|
||||
// writes the key-value pair to Data
|
||||
}
|
||||
}
|
||||
return Data;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Ini reading code
|
||||
|
||||
/// <summary>
|
||||
/// Reads an ini file and returns the content as an IniStructure. Returns null if an error occurred.
|
||||
/// </summary>
|
||||
/// <param name="Filename">The filename to read</param>
|
||||
/// <returns></returns>
|
||||
public static IniStructure ReadIni(string Filename)
|
||||
{
|
||||
string Data = ReadFile(Filename);
|
||||
if (Data == null)
|
||||
return null;
|
||||
|
||||
IniStructure data = InterpretIni(Data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static IniStructure InterpretIni(string Data)
|
||||
{
|
||||
IniStructure IniData = new IniStructure();
|
||||
string[] Lines = RemoveAndVerifyIni(DivideToLines(Data));
|
||||
// Divides the Data in lines, removes comments and empty lines
|
||||
// and verifies if the ini is not corrupted
|
||||
// Returns null if it is.
|
||||
if (Lines == null)
|
||||
return null;
|
||||
|
||||
if (IsLineACategoryDef(Lines[0]) != LineType.Category)
|
||||
{
|
||||
return null;
|
||||
// Ini is faulty - does not begin with a categorydef
|
||||
}
|
||||
string CurrentCategory = "";
|
||||
foreach (string line in Lines)
|
||||
{
|
||||
switch (IsLineACategoryDef(line))
|
||||
{
|
||||
case LineType.Category: // the line is a correct category definition
|
||||
string NewCat = line.Substring(1,line.Length - 2);
|
||||
IniData.AddCategory(NewCat); // adds the category to the IniData
|
||||
CurrentCategory = NewCat;
|
||||
break;
|
||||
case LineType.NotACategory: // the line is not a category definition
|
||||
string[] keyvalue = GetDataFromLine(line);
|
||||
IniData.AddValue(CurrentCategory, keyvalue[0], keyvalue[1]);
|
||||
// Adds the key-value to the current category
|
||||
break;
|
||||
case LineType.Faulty: // the line is faulty
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return IniData;
|
||||
}
|
||||
|
||||
private static string ReadFile(string filename)
|
||||
{ // Reads a file to a string.
|
||||
if (!File.Exists(filename))
|
||||
return null;
|
||||
StringBuilder IniData;
|
||||
try
|
||||
{
|
||||
using (FileStream IniStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
if (!IniStream.CanRead)
|
||||
return null;
|
||||
|
||||
using (StreamReader reader = new StreamReader(IniStream))
|
||||
{
|
||||
IniData = new StringBuilder();
|
||||
IniData.Append(reader.ReadToEnd());
|
||||
return IniData.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] GetDataFromLine(string Line)
|
||||
{
|
||||
// returns the key and the value of a key-value pair in "key=value" format.
|
||||
int EqualPos = 0;
|
||||
EqualPos = Line.IndexOf("=", 0);
|
||||
if (EqualPos < 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
string LeftKey = Line.Substring(0, EqualPos);
|
||||
string RightValue = Line.Substring(EqualPos + 1);
|
||||
|
||||
string[] ToReturn = {LeftKey, RightValue};
|
||||
return ToReturn;
|
||||
}
|
||||
|
||||
private enum LineType // return type for IsLineACategoryDef and LineVerify
|
||||
{
|
||||
NotACategory,
|
||||
Category,
|
||||
Faulty,
|
||||
Comment,
|
||||
Empty,
|
||||
Ok
|
||||
}
|
||||
|
||||
private static LineType IsLineACategoryDef(string Line)
|
||||
{
|
||||
if (Line.Length < 3)
|
||||
return LineType.NotACategory; // must be a short keyname like "k="
|
||||
|
||||
if (Line.Substring(0,1) == "[" & Line.Substring(Line.Length - 1, 1) == "]")
|
||||
// seems to be a categorydef
|
||||
{
|
||||
if (Line.IndexOf("=") != -1)
|
||||
// '=' found -> is incorrect for category def
|
||||
return LineType.Faulty;
|
||||
if (ContainsMoreThanOne(Line,'[') | ContainsMoreThanOne(Line, ']'))
|
||||
// two or more '[' or ']' found -> incorrect
|
||||
return LineType.Faulty;
|
||||
return LineType.Category;
|
||||
}
|
||||
return LineType.NotACategory;
|
||||
}
|
||||
|
||||
private static string[] DivideToLines(string Data)
|
||||
{ // Divides a string into lines
|
||||
string[] Lines = new string[Data.Length];
|
||||
int oldnewlinepos = 0;
|
||||
int LineCounter = 0;
|
||||
for (int i = 0; i < Data.Length; i++)
|
||||
{
|
||||
if (Data.ToCharArray(i,1)[0] == '\n')
|
||||
{
|
||||
Lines[LineCounter] = Data.Substring(oldnewlinepos, i - oldnewlinepos - 1);
|
||||
oldnewlinepos = i + 1;
|
||||
LineCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
// Lines[] array is too big: needs to be trimmed
|
||||
|
||||
Lines[LineCounter] = Data.Substring(oldnewlinepos, Data.Length - oldnewlinepos);
|
||||
string[] LinesTrimmed = new string[LineCounter + 1];
|
||||
for (int i = 0; i < LineCounter + 1; i++)
|
||||
{
|
||||
LinesTrimmed[i] = Lines[i];
|
||||
}
|
||||
return LinesTrimmed;
|
||||
}
|
||||
|
||||
private static bool ContainsMoreThanOne(string Data, char verify)
|
||||
{ // returns true if Data contains verify more than once
|
||||
char[] data = Data.ToCharArray();
|
||||
int count = 0;
|
||||
foreach (char c in data)
|
||||
{
|
||||
if (c == verify)
|
||||
count++;
|
||||
}
|
||||
if (count > 1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static LineType LineVerify(string line)
|
||||
{ // Verifies a line of an ini
|
||||
if (line == "")
|
||||
return LineType.Empty;
|
||||
|
||||
if (line.IndexOf(";") == 0 | line.IndexOf("#") == 0 | line.IndexOf("//") == 0)
|
||||
{
|
||||
return LineType.Comment; // line is a comment: ignore
|
||||
}
|
||||
|
||||
int equalindex = line.IndexOf('=');
|
||||
if (equalindex == 0)
|
||||
return LineType.Faulty; // an '=' cannot be on first place
|
||||
|
||||
if (equalindex != -1) // if = is found in line
|
||||
{
|
||||
// Verify: no '[' , ']' ,';' or '#' before the '='
|
||||
if (line.IndexOf('[', 0, equalindex) != -1
|
||||
| line.IndexOf(']', 0, equalindex) != -1
|
||||
| line.IndexOf(';', 0, equalindex) != -1
|
||||
| line.IndexOf('#', 0, equalindex) != -1)
|
||||
return LineType.Faulty;
|
||||
}
|
||||
|
||||
return LineType.Ok;
|
||||
}
|
||||
|
||||
private static string[] RemoveAndVerifyIni(string[] Lines)
|
||||
{
|
||||
// removes empty lines and comments, and verifies every line
|
||||
string[] temp = new string[Lines.Length];
|
||||
int TempCounter = 0; // number of lines to return
|
||||
foreach (string line in Lines)
|
||||
{
|
||||
switch (LineVerify(line))
|
||||
{
|
||||
case LineType.Faulty: // line is faulty
|
||||
return null;
|
||||
case LineType.Comment: // line is a comment
|
||||
continue;
|
||||
case LineType.Ok: // line is ok
|
||||
temp[TempCounter] = line;
|
||||
TempCounter++;
|
||||
break;
|
||||
case LineType.Empty: // line is empty
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// the temp[] array is too big: needs to be trimmed.
|
||||
string[] OKLines = new string[TempCounter];
|
||||
for (int i = 0; i < TempCounter; i++)
|
||||
{
|
||||
OKLines[i] = temp[i];
|
||||
}
|
||||
return OKLines;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Infrastructure;
|
||||
using System.Threading;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Helpers
|
||||
{
|
||||
/* CLASS ORIGIN: Spearhead project */
|
||||
public class MessageQueue
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private volatile bool enabled, suspended;
|
||||
|
||||
private readonly Queue<KeyValuePair<ContactInfo, string>> queue = new Queue<KeyValuePair<ContactInfo, string>>(5);
|
||||
private Thread QueueThread;
|
||||
|
||||
private readonly ManualResetEvent waitHandle = new ManualResetEvent(true);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
protected enum CommonWaitTime : int
|
||||
{
|
||||
QueueSuspension = 50,
|
||||
QueueItemProcessed = 1000,
|
||||
QueueProcessed = 1000,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler MessageSending;
|
||||
public event EventHandler MessageSent;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors & .dctors
|
||||
|
||||
public MessageQueue()
|
||||
{
|
||||
QueueThread = InitializeQueueThread();
|
||||
}
|
||||
|
||||
protected virtual Thread InitializeQueueThread()
|
||||
{
|
||||
Thread thread = new Thread(ProcessQueue);
|
||||
thread.IsBackground = true;
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
~MessageQueue()
|
||||
{
|
||||
SetState(false);
|
||||
waitHandle.Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public bool Suspended
|
||||
{
|
||||
get
|
||||
{
|
||||
return suspended;
|
||||
}
|
||||
}
|
||||
|
||||
public ManualResetEvent WaitHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
return waitHandle;
|
||||
}
|
||||
}
|
||||
|
||||
protected Queue<KeyValuePair<ContactInfo, string>> Queue
|
||||
{
|
||||
get { return queue; }
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public bool QueueHasItems
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (Queue)
|
||||
return Queue.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool ClearQueueWhenDisabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Virtuals
|
||||
|
||||
protected virtual void ProcessQueue()
|
||||
{
|
||||
while (Enabled)
|
||||
{
|
||||
while (suspended)
|
||||
Wait(CommonWaitTime.QueueSuspension);
|
||||
|
||||
lock (Queue)
|
||||
{
|
||||
while (QueueHasItems)
|
||||
{
|
||||
waitHandle.Reset();
|
||||
RaiseMessageForwardingEvent();
|
||||
|
||||
DequeueAndSendMessage();
|
||||
Wait(QueueItemProcessedWaitTime);
|
||||
|
||||
RaiseMessageForwardedEvent();
|
||||
}
|
||||
|
||||
waitHandle.Set();
|
||||
}
|
||||
|
||||
Wait(QueueProcessedWaitTime);
|
||||
}
|
||||
|
||||
waitHandle.Set();
|
||||
}
|
||||
|
||||
protected void DequeueAndSendMessage()
|
||||
{
|
||||
lock (Queue)
|
||||
{
|
||||
KeyValuePair<ContactInfo, string> data = Queue.Dequeue();
|
||||
SendMessage(data.Key, data.Value);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SendMessage(ContactInfo recipient, string message)
|
||||
{
|
||||
recipient.SendMessage(message);
|
||||
}
|
||||
|
||||
protected virtual int QueueItemProcessedWaitTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)CommonWaitTime.QueueItemProcessed;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual int QueueProcessedWaitTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)CommonWaitTime.QueueProcessed;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void SuspendQueue()
|
||||
{
|
||||
suspended = true;
|
||||
}
|
||||
|
||||
public void ResumeQueue()
|
||||
{
|
||||
suspended = false;
|
||||
}
|
||||
|
||||
public void EnqueueMessage(ContactInfo to, string message)
|
||||
{
|
||||
lock (queue)
|
||||
queue.Enqueue(new KeyValuePair<ContactInfo, string>(to, message));
|
||||
|
||||
SetState(true);
|
||||
}
|
||||
|
||||
public void SetState(bool enabled)
|
||||
{
|
||||
// Queue is used as a sync object here...
|
||||
lock (Queue)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
if ((QueueThread.ThreadState & ThreadState.Stopped) == ThreadState.Stopped)
|
||||
QueueThread = InitializeQueueThread();
|
||||
|
||||
if ((QueueThread.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
|
||||
QueueThread.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Queue.Clear();
|
||||
}
|
||||
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
protected void RaiseMessageForwardingEvent()
|
||||
{
|
||||
if (MessageSending != null)
|
||||
MessageSending(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected void RaiseMessageForwardedEvent()
|
||||
{
|
||||
if (MessageSent != null)
|
||||
MessageSent(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected void Wait(CommonWaitTime miliseconds)
|
||||
{
|
||||
Wait((int)miliseconds);
|
||||
}
|
||||
|
||||
protected void Wait(int miliseconds)
|
||||
{
|
||||
Thread.Sleep(miliseconds);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Security;
|
||||
using System.Security.Policy;
|
||||
using System.IO;
|
||||
using Virtuoso.Miranda.Plugins.Infrastructure;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Helpers
|
||||
{
|
||||
/* CLASS ORIGIN: Loki project */
|
||||
public abstract class Sandbox : RemoteObject
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private AppDomain hostingAppDomain;
|
||||
protected AppDomain HostingAppDomain
|
||||
{
|
||||
get { return hostingAppDomain; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nested classes
|
||||
|
||||
private sealed class MirandaContextInitHelper : RemoteObject
|
||||
{
|
||||
public MirandaContextInitHelper(MirandaContext context)
|
||||
{
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
MirandaContext.InvalidateCurrent();
|
||||
MirandaContext.InitializeCurrent(context);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
protected Sandbox() { }
|
||||
|
||||
public static void Unload(Sandbox sandbox)
|
||||
{
|
||||
if (sandbox == null)
|
||||
throw new ArgumentNullException("sandbox");
|
||||
|
||||
if (sandbox.hostingAppDomain == null)
|
||||
throw new ArgumentException();
|
||||
|
||||
if (sandbox.hostingAppDomain == AppDomain.CurrentDomain)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_UnableToUnloadPluginMangerFromCurrentAppDomain);
|
||||
|
||||
sandbox.OnSandboxUnload();
|
||||
sandbox.UnloadHostingAppDomain();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Virtuals
|
||||
|
||||
protected virtual void InitializeAppDomainSetup(AppDomainSetup domainSetup) { }
|
||||
|
||||
protected virtual void OnSandboxUnload() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
protected static StrongName GetStrongName(Assembly assembly)
|
||||
{
|
||||
if (assembly == null)
|
||||
throw new ArgumentNullException("assembly");
|
||||
|
||||
AssemblyName assemblyName = assembly.GetName();
|
||||
Debug.Assert(assemblyName != null, "Could not get assembly name");
|
||||
|
||||
byte[] publicKey = assemblyName.GetPublicKey();
|
||||
if (publicKey == null || publicKey.Length == 0)
|
||||
throw new InvalidOperationException(String.Format("{0} is not strongly named", assembly));
|
||||
|
||||
StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
|
||||
return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected void SetUpHostingAppDomain(string name)
|
||||
{
|
||||
SetUpHostingAppDomain(name, null, null);
|
||||
}
|
||||
|
||||
protected void SetUpHostingAppDomain(string name, Evidence evidence, PermissionSet permissions, params StrongName[] fullTrust)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
if (hostingAppDomain != null)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
AppDomainSetup currentSetup = AppDomain.CurrentDomain.SetupInformation;
|
||||
AppDomainSetup domainSetup = new AppDomainSetup();
|
||||
|
||||
domainSetup.ApplicationName = name;
|
||||
domainSetup.ApplicationBase = currentSetup.ApplicationBase;
|
||||
domainSetup.PrivateBinPath = String.Format("{0};{1};", MirandaEnvironment.MirandaPluginsFolderRelativePath, MirandaEnvironment.ManagedPluginsFolderRelativePath);
|
||||
domainSetup.ConfigurationFile = currentSetup.ConfigurationFile;
|
||||
|
||||
InitializeAppDomainSetup(domainSetup);
|
||||
|
||||
if (permissions == null)
|
||||
hostingAppDomain = AppDomain.CreateDomain(name, null, domainSetup);
|
||||
else
|
||||
hostingAppDomain = AppDomain.CreateDomain(name, evidence, domainSetup, permissions, fullTrust);
|
||||
}
|
||||
|
||||
protected void UnloadHostingAppDomain()
|
||||
{
|
||||
if (hostingAppDomain == null)
|
||||
throw new InvalidOperationException();
|
||||
else
|
||||
{
|
||||
AppDomain.Unload(hostingAppDomain);
|
||||
hostingAppDomain = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected T InstantiateRemoteObject<T>(string assemblyName, string typeName, params object[] args) where T : class
|
||||
{
|
||||
return Activator.CreateInstance(hostingAppDomain, assemblyName, typeName, true, BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public, null, args, null, null, null).Unwrap() as T;
|
||||
}
|
||||
|
||||
protected T InstantiateRemoteObjectFrom<T>(string assemblyFile, string typeName, params object[] args) where T : class
|
||||
{
|
||||
return Activator.CreateInstanceFrom(hostingAppDomain, assemblyFile, typeName, true, BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public, null, args, null, null, null).Unwrap() as T;
|
||||
}
|
||||
|
||||
protected void InitializeRemoteContext(MirandaContext context)
|
||||
{
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
if (hostingAppDomain == null)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
InstantiateRemoteObject<MirandaContextInitHelper>(Assembly.GetExecutingAssembly().FullName, typeof(MirandaContextInitHelper).FullName, context);
|
||||
}
|
||||
|
||||
public void SetUnhandledExceptionHandler(UnhandledExceptionEventHandler handler)
|
||||
{
|
||||
hostingAppDomain.UnhandledException += handler;
|
||||
}
|
||||
|
||||
public void RemoveUnhandledExceptionHandler(UnhandledExceptionEventHandler handler)
|
||||
{
|
||||
hostingAppDomain.UnhandledException -= handler;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Helpers
|
||||
{
|
||||
internal class TypeInstanceCache<T> : Dictionary<Type, T>
|
||||
{
|
||||
#region .ctors
|
||||
|
||||
public TypeInstanceCache() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public T Instantiate(Type type)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (ContainsKey(type))
|
||||
return this[type];
|
||||
else
|
||||
{
|
||||
T instance = (T)Activator.CreateInstance(type);
|
||||
this[type] = instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Helpers
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public static uint GetTimestamp()
|
||||
{
|
||||
return GetTimestamp(DateTime.Now);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static uint GetTimestamp(DateTime dateTime)
|
||||
{
|
||||
return (uint)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user