Initial Commit

This commit is contained in:
Abdel
2015-09-12 19:58:10 -04:00
commit f612fc4f3f
71 changed files with 12107 additions and 0 deletions

217
.gitignore vendored Normal file
View File

@@ -0,0 +1,217 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

10
Local.testsettings Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Local" id="e94baad6-3eb3-4263-9119-9d52054425a8" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>Il s'agit des paramètres de test par défaut pour une série de tests locale.</Description>
<Deployment enabled="false" />
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
</AgentRule>
</Execution>
</TestSettings>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Trace et impact de test" id="4ea1a2c1-1cee-4862-a218-6c38c632b9cc" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>Il s'agit des paramètres de test pour trace et impact de test.</Description>
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
<DataCollectors>
<DataCollector uri="datacollector://microsoft/SystemInfo/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TestTools.DataCollection.SystemInfo.SystemInfoDataCollector, Microsoft.VisualStudio.TestTools.DataCollection.SystemInfo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Informations système">
</DataCollector>
<DataCollector uri="datacollector://microsoft/ActionLog/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TestTools.ManualTest.ActionLog.ActionLogPlugin, Microsoft.VisualStudio.TestTools.ManualTest.ActionLog, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Actions">
</DataCollector>
<DataCollector uri="datacollector://microsoft/HttpProxy/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.HttpProxyCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Proxy client ASP.NET pour IntelliTrace et l'impact de test">
</DataCollector>
<DataCollector uri="datacollector://microsoft/TestImpact/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.TestImpactDataCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Impact de test">
</DataCollector>
<DataCollector uri="datacollector://microsoft/TraceDebugger/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.TraceDebuggerDataCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="IntelliTrace">
</DataCollector>
</DataCollectors>
</AgentRule>
</Execution>
</TestSettings>

20
vCardEditor.sln Normal file
View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vCardEditor", "vCardEditor\vCardEditor.csproj", "{A0D2ACEB-1BCC-4E7F-9E7D-2BE25A7ABE22}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0D2ACEB-1BCC-4E7F-9E7D-2BE25A7ABE22}.Debug|x86.ActiveCfg = Debug|x86
{A0D2ACEB-1BCC-4E7F-9E7D-2BE25A7ABE22}.Debug|x86.Build.0 = Debug|x86
{A0D2ACEB-1BCC-4E7F-9E7D-2BE25A7ABE22}.Release|x86.ActiveCfg = Release|x86
{A0D2ACEB-1BCC-4E7F-9E7D-2BE25A7ABE22}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

6
vCardEditor.vsmdi Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<TestList name="Listes de tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
<RunConfiguration id="e94baad6-3eb3-4263-9119-9d52054425a8" name="Local" storage="local.testsettings" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</TestList>
</TestLists>

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
namespace VCFEditor
{
public class ContactRepository : IContactRepository
{
public string fileName { get; set; }
private BindingList<Contact> _contacts;
public BindingList<Contact> Contacts
{
get
{
if (_contacts == null)
_contacts = new BindingList<Contact>();
return _contacts;
}
set
{
_contacts = value;
}
}
/// <summary>
/// Formatted name.
/// </summary>
public const string KeyName = "FN";
/// <summary>
/// Load contacts.
/// 1- Parse the file
/// 2-
/// </summary>
/// <param name="path"></param>
public BindingList<Contact> LoadContacts(string fileName)
{
string[] lines = File.ReadAllLines(fileName);
string[] parts;
var contact = new Contact();
//Prevent from adding contacts to existings ones.
Contacts.Clear();
for (int i = 0; i < lines.Length; i++)
{
contact.RawContent.AppendLine(lines[i]);
if (lines[i] == "END:VCARD")
{
Contacts.Add(contact);
contact = new Contact();
}
else
{
parts = lines[i].Split(new char[] { ':' });
if (string.Compare(parts[0], KeyName) == 0)
contact.Name = parts[1];
}
}
return Contacts;
}
/// <summary>
/// Save the contact to the file.
/// </summary>
/// <param name="path">Path to the new file, else if null, we overwrite the same file</param>
public void SaveContacts(string fileName)
{
//overwrite the same file, else save as another file.
if (string.IsNullOrEmpty(fileName))
fileName = this.fileName;
StringBuilder sb = new StringBuilder();
foreach (var entry in Contacts)
sb.Append(entry.RawContent);
File.WriteAllText(fileName, sb.ToString());
}
/// <summary>
/// Delete contacted that are selected.
/// </summary>
public void DeleteContact()
{
if (_contacts != null && _contacts.Count > 0)
{
//loop from the back to prevent index mangling...
for (int i = _contacts.Count - 1; i > -1; i--)
{
if (_contacts[i].isSelected)
_contacts.RemoveAt(i);
}
}
}
public vCard ParseContactAt(int index)
{
vCard card = null;
Contact contact = _contacts[index];
using (MemoryStream s = GenerateStreamFromString(contact.RawContent.ToString()))
using (TextReader streamReader = new StreamReader(s, Encoding.Default))
{
card = new vCard(streamReader);
}
return card;
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
namespace VCFEditor
{
public interface IContactRepository
{
string fileName { get; set; }
BindingList<Contact> Contacts { get; set; }
BindingList<Contact> LoadContacts(string fileName);
void SaveContacts(string fileName);
vCard ParseContactAt(int index);
void DeleteContact();
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VCFEditor.Model
{
/// <summary>
///
/// </summary>
public class Contact : INotifyPropertyChanged
{
private string _name;
[DisplayName(" ")]
public bool isSelected { get; set; }
[DisplayName("Name")]
public string Name
{
get { return _name; }
set
{
_name = value;
this.NotifyPropertyChanged("Name");
}
}
[Browsable(false)]
public StringBuilder RawContent { get; set; }
public Contact()
{
RawContent = new StringBuilder();
isSelected = false;
}
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using VCFEditor.View;
using System.ComponentModel;
namespace VCFEditor.Presenter
{
public class MainPresenter
{
private readonly IMainView _view;
private readonly IContactRepository _repository;
public MainPresenter(IMainView view, IContactRepository repository)
{
_view = view;
_repository = repository;
//hook event from the view to event handler present in this presenter.
_view.NewFileOpened += NewFileOpened;
_view.SaveContactsSelected += SaveContacts;
_view.ChangeContactsSelected += ChangeContactSelected;
_view.DeleteContact += DeleteContact;
}
private void DeleteContact(object sender, EventArgs e)
{
_repository.DeleteContact();
}
private void SaveContacts(object sender, EventArgs e)
{
_repository.SaveContacts(_repository.fileName);
}
public void NewFileOpened(object sender, EventArg<string> e)
{
DisplayContacts(e.Data);
}
public void ChangeContactSelected(object sender, EventArg<int> e)
{
if (e.Data > -1)
{
int index = e.Data;
vCard card = _repository.ParseContactAt(index);
if (card != null)
{
_view.DisplayContactDetail(card);
}
}
}
public void DisplayContacts(string path)
{
if (!string.IsNullOrEmpty(path))
{
_repository.LoadContacts(path);
_view.DisplayContacts(_repository.Contacts);
}
}
}
}

28
vCardEditor/Program.cs Normal file
View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using vCardEditor.View;
using VCFEditor.Presenter;
using VCFEditor;
namespace vCardEditor
{
static class Program
{
/// <summary>
/// Point d'entrée principal de l'application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = new MainForm();
var presenter = new MainPresenter(mainForm, new ContactRepository());
Application.Run(mainForm);
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Les informations générales relatives à un assembly dépendent de
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
// associées à un assembly.
[assembly: AssemblyTitle("vCardEditor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("vCardEditor")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
// aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
// COM, affectez la valeur true à l'attribut ComVisible sur ce type.
[assembly: ComVisible(false)]
// Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
[assembly: Guid("22e4348d-1699-4db2-be45-7407352a41d2")]
// Les informations de version pour un assembly se composent des quatre valeurs suivantes :
//
// Version principale
// Version secondaire
// Numéro de build
// Révision
//
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
// en utilisant '*', comme indiqué ci-dessous :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.34209
//
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
namespace vCardEditor.Properties
{
/// <summary>
/// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
/// </summary>
// Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
// avec l'option /str ou régénérez votre projet VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("vCardEditor.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Remplace la propriété CurrentUICulture du thread actuel pour toutes
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?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.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: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" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</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>
</root>

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace vCardEditor.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,216 @@
vCard Class Library for .NET
Copyright (c) 2007-2009 David Pinch (davepinch@gmail.com).
Please refer to README.TXT in the distribution archive. If you do
not have a copy of the archive, you may download the latest version
of this library from http://www.thoughtproject.com/Libraries/vCard/
This library is distributed under the terms of the Lesser General
Public License. Please refer to LICENSE.TXT for the exact terms.
History
------------------------------------------------------------------------
2009-10-08: Version 0.4
------------------------------------------------------------------------
1. Unit tests have been upgraded to NUnit 2.5.2.
2. Per the Microsoft guidelines for class library development, all string
properties are expected to return String.Empty instead of null (in
cases where the property is blank). This is already the case in
this library but the implementation was problematic. Instead each
string getter now takes the following form:
return this.property ?? string.Empty;
Previously the code attempted to translate null to string.Empty whenever
the value was assigned -- in the constructor, in the setter, etc. This
is prone to error. The form shown above is used instead.
3. Renames. The following types were renamed to comply with standard
naming conventions. Any code will need to be fixed. Fixes should be
minor only.
Per class library design guidelines, flag enumerations should be
named with a plural name. See FxCop rule FlagsEnumsShouldHavePluralNames.
These changes are simple to fix in code; simple add an "s" whereever you
reference the enumeration.
- vCardDeliveryAddressType => vCardDeliveryAddressTypes
- vCardPhoneType => vCardPhoneTypes
- vCardWebSiteType => vCardWebSiteTypes
Per class library design guidelines, the term "WebSite" is actually
a discrete term "website". Refer to rule CompoundWordsShouldBeCasedCorrectly
in FxCop. The following types have been renamed:
- vCardWebSite => vCardWebsite
- vCardWebSiteCollection => vCardWebsiteCollection
- vCardWebSiteType => vCardWebsiteType
3. Non-Breaking Changes:
The following changes are internal fixes that are not expected to
cause compilation issues.
- Assembly marked as language neutral (set to U.S. English).
- vCardStandardWriter no longer unnecessarily initializes embedInternetImages
- vCardStandardWriterOptions is now a flags enumeration
- vCardSubpropertyCollection uses StringComparison.OrdinalIgnoreCase.
- vCardStandardReader recognizes the date format exported by Outlook 2007.
- Updated various XML comments.
Some collections have overloads that return the index of a named
value, e.g. vCardSubpropertyCollection.IndexOf(name). Internally
these functions perform a comparison using StringComparison.OrdinalIgnoreCase.
This should have no impact unless you were using the library under
a very unique language/environment.
------------------------------------------------------------------------
2007-08-xx: Version 0.3
------------------------------------------------------------------------
Thank you to many people who have written with kind comments and
suggestions for the library. The biggest change in this version
is a complete refactoring of the code for reading and writing
the file formats. The main vCard object model is now a generic
model. Format-specific code has been moved to separate classes
for easier maintenance and support for vCard-compatible formats.
Some changes will probably break your code. For example, the
library now supports multiple notes (previously only one note
per vCard was supported). The majority of changes will be
easy to fix, usually just by using the Intellisense(tm) in your
Visual Studio IDE. Please refer to the Unit Testing solution
if you need examples of using the API in various ways. The
number of unit tests have been expanded substantially.
- Added support for quoted-printable and standard MIME escape
encoding. The read/write process has been completely refactored
into a separate API to better support multiple vCard formats.
- Added vCardReader and vCardWriter, both abstract classes. They
define the core interfaces for creating format-specific readers
and writers.
- Added vCardStandardReader and vCardStandardWriter. These two
classes implement the vCard 2.1 and 3.0 text format specifications.
These classes are fairly complex due to the wide variety of
interpretations found in the wild!
- Removed all format and encoding-specific code from the main
vCard object model. Anything format-specific is expected to
be implemented in a reader or writer class. Currently only
the 2.1 and 3.0 formats are implemented, although future
versions will support RFD, hCard and other variations.
Therefore it makes no sense to have anything format-specific
in the main object model.
- Added support for multiple web sites. The vCard.Url property
was removed in favor of vCard.WebSites, a collection. See
new items: vCardWebSite, vCardWebSiteCollection, and
vCardWebSiteType. Import and export logic also updated.
- Added support for multiple notes/comments. The vCard.Note
property was removed in favor of vCard.Notes, a collection.
- Added support for delivery addresses and delivery labels.
The current level of support is sufficient for Microsoft Outlook
but needs some more work for total vCard compliance.
- Added vCard.AccessClassification. This indicates the
intended access/permissions of the vCard, such as private,
public or confidential. It corresponds to the CLASS
property of the vCard specification.
- Added vCard.Categories (a string collection). This contains
any user-defined categories or keywords. It corresponds
with the CATEGORIES property of the vCard specification.
- Added vCard.DisplayName. This maps to the NAME property and
specifies the display name of the vCard. A vCard application
might show this name as a title or header.
- Added vCard.Latitude and vCard.Longitude. These correspond with
the GEO property of the specification. Usage seems to be
very rare but is implemented here for completeness.
- Added vCard.Photos, a collection of vCardPhoto objects.
A photo can be referenced as a URL or specified directly
with a bitmap or byte array.
- Added vCard.RevisionDate (nullable date). This contains the
last revision date of the vCard. The library does not
update this value when you make changes; you need to set
the revision date yourself. This maps to the REV property
of the specification.
- Renamed vCardPhone.Subtype to vCardPhone.PhoneType in order to
be consistent with the naming conventions used elsewhere in
the library.
And much more.
------------------------------------------------------------------------
2007-05-14: Version 0.2
------------------------------------------------------------------------
vCard Format/Specification Changes:
- Added support for the KEY property, which is used to embed
a certificate in the vCard. Only the BASE64 encoding, used by
Microsoft Outlook and many PIMs, is supported. Thanks for
Martin Meraner
- Added support for the MAILER property. This property identifies
the software that generated the vCard; it is described in
section 2.4.3 of the vCard 2.1 specification.
- Added support for the SOURCE vCard property. This property
identifies the URI of a directory that provided information
for the vCard contents (e.g., an LDAP URL).
- Added support for the UID property. This property is a string
that uniquely identifies the vCard in relation to other vCards.
There is no standard but typical ID strings might be URLs,
GUIDs, etc.
- Added support for the X-WAB-GENDER extended property. This
property identifies the gender of the contact; it may not be
supported elsewhere and therefore should be used with care.
It is an extended property used by Microsoft Outlook.
- Added support for the ROLE property. This property describes
the role of the person at his/her organization, e.g. Programmer
or Executive, etc.
Class Library API Changes:
- Added the standard .NET constructors to the vCardException class.
- Added a unit testing project (designed for NUnit).
- Added vCardCertificate
- Added vCardCertificateCollection
- Added vCardDeliveryLabel
- Added vCardDeliveryLabelType
- Added vCardGender
- Added vCardSource
- Added vCardSourceCollection
- Added vCardValueType
- Fixed and expanded inline and XML comments.
- Fixed typo of vCardPhone.IsCelluar to vCardPhone.IsCellular.
------------------------------------------------------------------------
2007-03-07: Version 0.1
------------------------------------------------------------------------
Initial release on www.thoughtproject.com/Libraries/vCards/

View File

@@ -0,0 +1,22 @@

vCard Properties
--------------------------------------------------------------------------
X-MS-OL-DEFAULT-POSTAL-ADDRESS
This property is generated by Microsoft Outlook 2007. It appears
to define the default postal address (which is shown as a checkbox
in the Outlook 2007 interface) but specific technical details are
unknown. The property is ignored in the current version of the library.
X-MS-IMADDRESS
Microsoft extension to hold an instant message address.
X-MS-OL-DESIGN
Research needed.

View File

@@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "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 THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@@ -0,0 +1,90 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.34209
//
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Thought.vCards {
using System;
/// <summary>
/// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
/// </summary>
// Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
// avec l'option /str ou régénérez votre projet VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class WarningMessages {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal WarningMessages() {
}
/// <summary>
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Thought.vCards.WarningMessages", typeof(WarningMessages).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Remplace la propriété CurrentUICulture du thread actuel pour toutes
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Line {0} A blank line was encountered. This is not allowed in the vCard specification..
/// </summary>
internal static string BlankLine {
get {
return ResourceManager.GetString("BlankLine", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Line {0}: A colon (:) is missing. All properties must be in NAME:VALUE format..
/// </summary>
internal static string ColonMissing {
get {
return ResourceManager.GetString("ColonMissing", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Line {0}: The name section of the property is empty..
/// </summary>
internal static string EmptyName {
get {
return ResourceManager.GetString("EmptyName", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,129 @@
<?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>
<data name="BlankLine" xml:space="preserve">
<value>Line {0} A blank line was encountered. This is not allowed in the vCard specification.</value>
</data>
<data name="ColonMissing" xml:space="preserve">
<value>Line {0}: A colon (:) is missing. All properties must be in NAME:VALUE format.</value>
</data>
<data name="EmptyName" xml:space="preserve">
<value>Line {0}: The name section of the property is empty.</value>
</data>
</root>

View File

@@ -0,0 +1,768 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
namespace Thought.vCards
{
/// <summary>
/// A vCard object for exchanging personal contact information.
/// </summary>
/// <remarks>
/// <para>
/// A vCard contains personal information, such as postal
/// addresses, public security certificates, email addresses, and
/// web sites. The vCard specification makes it possible for
/// different computer programs to exchange personal contact
/// information; for example, a vCard can be attached to an email or
/// sent over a wireless connection.
/// </para>
/// <para>
/// The standard vCard format is a text file with properties in
/// name:value format. However, there are multiple versions of
/// this format as well as compatible alternatives in XML and
/// HTML formats. This class library aims to accomodate these
/// variations but be aware some some formats do not support
/// all possible properties.
/// </para>
/// </remarks>
[Serializable]
public class vCard
{
private vCardAccessClassification accessClassification;
private string additionalNames;
private DateTime? birthDate;
private StringCollection categories;
private string department;
private string displayName;
private string familyName;
private string formattedName;
private vCardGender gender;
private string givenName;
private float? latitude;
private float? longitude;
private string mailer;
private string namePrefix;
private string nameSuffix;
private StringCollection nicknames;
private string office;
private string organization;
private string productId;
private DateTime? revisionDate;
private string role;
private string timeZone;
private string title;
private string uniqueId;
private vCardCertificateCollection certificates;
private vCardDeliveryAddressCollection deliveryAddresses;
private vCardDeliveryLabelCollection deliveryLabels;
private vCardEmailAddressCollection emailAddresses;
private vCardNoteCollection notes;
private vCardPhoneCollection phones;
private vCardPhotoCollection photos;
private vCardSourceCollection sources;
private vCardWebsiteCollection websites;
/// <summary>
/// Initializes a new instance of the <see cref="vCard"/> class.
/// </summary>
public vCard()
{
// Per Microsoft best practices, string properties should
// never return null. String properties should always
// return String.Empty.
this.additionalNames = string.Empty;
this.department = string.Empty;
this.displayName = string.Empty;
this.familyName = string.Empty;
this.formattedName = string.Empty;
this.givenName = string.Empty;
this.mailer = string.Empty;
this.namePrefix = string.Empty;
this.nameSuffix = string.Empty;
this.office = string.Empty;
this.organization = string.Empty;
this.productId = string.Empty;
this.role = string.Empty;
this.timeZone = string.Empty;
this.title = string.Empty;
this.uniqueId = string.Empty;
this.categories = new StringCollection();
this.certificates = new vCardCertificateCollection();
this.deliveryAddresses = new vCardDeliveryAddressCollection();
this.deliveryLabels = new vCardDeliveryLabelCollection();
this.emailAddresses = new vCardEmailAddressCollection();
this.nicknames = new StringCollection();
this.notes = new vCardNoteCollection();
this.phones = new vCardPhoneCollection();
this.photos = new vCardPhotoCollection();
this.sources = new vCardSourceCollection();
this.websites = new vCardWebsiteCollection();
}
/// <summary>
/// Loads a new instance of the <see cref="vCard"/> class
/// from a text reader.
/// </summary>
/// <param name="input">
/// An initialized text reader.
/// </param>
public vCard(TextReader input)
: this()
{
vCardReader reader = new vCardStandardReader();
reader.ReadInto(this, input);
}
/// <summary>
/// Loads a new instance of the <see cref="vCard"/> class
/// from a text file.
/// </summary>
/// <param name="path">
/// The path to a text file containing vCard data in
/// any recognized vCard format.
/// </param>
public vCard(string path)
: this()
{
using (StreamReader streamReader = new StreamReader(path))
{
vCardReader reader = new vCardStandardReader();
reader.ReadInto(this, streamReader);
}
//String example = "BEGIN:VCARD\nVERSION:3.0\nN:;Saad;;;\nFN:Saad\nTEL;TYPE=CELL:418-271-3874\nTEL;TYPE=HOME:418-524-7721\nEND:VCARD";
// using (MemoryStream s = GenerateStreamFromString(example))
//{
// vCardReader reader = new vCardStandardReader();
// TextReader streamReader = new StreamReader(s, Encoding.Default);
// reader.ReadInto(this, streamReader);
//}
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
/// <summary>
/// The security access classification of the vCard owner (e.g. private).
/// </summary>
public vCardAccessClassification AccessClassification
{
get
{
return this.accessClassification;
}
set
{
this.accessClassification = value;
}
}
/// <summary>
/// Any additional (e.g. middle) names of the person.
/// </summary>
/// <seealso cref="FamilyName"/>
/// <seealso cref="FormattedName"/>
/// <seealso cref="GivenName"/>
/// <seealso cref="Nicknames"/>
public string AdditionalNames
{
get
{
return this.additionalNames ?? string.Empty;
}
set
{
this.additionalNames = value;
}
}
/// <summary>
/// The birthdate of the person.
/// </summary>
public DateTime? BirthDate
{
get
{
return this.birthDate;
}
set
{
this.birthDate = value;
}
}
/// <summary>
/// Categories of the vCard.
/// </summary>
/// <remarks>
/// This property is a collection of strings containing
/// keywords or category names.
/// </remarks>
public StringCollection Categories
{
get
{
return this.categories;
}
}
/// <summary>
/// Public key certificates attached to the vCard.
/// </summary>
/// <seealso cref="vCardCertificate"/>
public vCardCertificateCollection Certificates
{
get
{
return this.certificates;
}
}
/// <summary>
/// Delivery addresses associated with the person.
/// </summary>
public vCardDeliveryAddressCollection DeliveryAddresses
{
get
{
return this.deliveryAddresses;
}
}
/// <summary>
/// Formatted delivery labels.
/// </summary>
public vCardDeliveryLabelCollection DeliveryLabels
{
get
{
return this.deliveryLabels;
}
}
/// <summary>
/// The department of the person in the organization.
/// </summary>
/// <seealso cref="Office"/>
/// <seealso cref="Organization"/>
public string Department
{
get
{
return this.department ?? string.Empty;
}
set
{
this.department = value;
}
}
/// <summary>
/// The display name of the vCard.
/// </summary>
/// <remarks>
/// This property is used by vCard applications for titles,
/// headers, and other visual elements.
/// </remarks>
public string DisplayName
{
get
{
return this.displayName ?? string.Empty;
}
set
{
this.displayName = value;
}
}
/// <summary>
/// A collection of <see cref="vCardEmailAddress"/> objects for the person.
/// </summary>
/// <seealso cref="vCardEmailAddress"/>
public vCardEmailAddressCollection EmailAddresses
{
get
{
return this.emailAddresses;
}
}
/// <summary>
/// The family (last) name of the person.
/// </summary>
/// <seealso cref="AdditionalNames"/>
/// <seealso cref="FormattedName"/>
/// <seealso cref="GivenName"/>
/// <seealso cref="Nicknames"/>
public string FamilyName
{
get
{
return this.familyName ?? string.Empty;
}
set
{
this.familyName = value;
}
}
/// <summary>
/// The formatted name of the person.
/// </summary>
/// <remarks>
/// This property allows the name of the person to be
/// written in a manner specific to his or her culture.
/// The formatted name is not required to strictly
/// correspond with the family name, given name, etc.
/// </remarks>
/// <seealso cref="AdditionalNames"/>
/// <seealso cref="FamilyName"/>
/// <seealso cref="GivenName"/>
/// <seealso cref="Nicknames"/>
public string FormattedName
{
get
{
return this.formattedName ?? string.Empty;
}
set
{
this.formattedName = value;
}
}
/// <summary>
/// The gender of the person.
/// </summary>
/// <remarks>
/// The vCard specification does not define a property
/// to indicate the gender of the contact. Microsoft
/// Outlook implements it as a custom property named
/// X-WAB-GENDER.
/// </remarks>
/// <seealso cref="vCardGender"/>
public vCardGender Gender
{
get
{
return this.gender;
}
set
{
this.gender = value;
}
}
/// <summary>
/// The given (first) name of the person.
/// </summary>
/// <seealso cref="AdditionalNames"/>
/// <seealso cref="FamilyName"/>
/// <seealso cref="FormattedName"/>
/// <seealso cref="Nicknames"/>
public string GivenName
{
get
{
return this.givenName ?? string.Empty;
}
set
{
this.givenName = value;
}
}
/// <summary>
/// The latitude of the person in decimal degrees.
/// </summary>
/// <seealso cref="Longitude"/>
public float? Latitude
{
get
{
return this.latitude;
}
set
{
this.latitude = value;
}
}
/// <summary>
/// The longitude of the person in decimal degrees.
/// </summary>
/// <seealso cref="Latitude"/>
public float? Longitude
{
get
{
return this.longitude;
}
set
{
this.longitude = value;
}
}
/// <summary>
/// The mail software used by the person.
/// </summary>
public string Mailer
{
get
{
return this.mailer ?? string.Empty;
}
set
{
this.mailer = value;
}
}
/// <summary>
/// The prefix (e.g. "Mr.") of the person.
/// </summary>
/// <seealso cref="NameSuffix"/>
public string NamePrefix
{
get
{
return this.namePrefix ?? string.Empty;
}
set
{
this.namePrefix = value;
}
}
/// <summary>
/// The suffix (e.g. "Jr.") of the person.
/// </summary>
/// <seealso cref="NamePrefix"/>
public string NameSuffix
{
get
{
return this.nameSuffix ?? string.Empty;
}
set
{
this.nameSuffix = value;
}
}
/// <summary>
/// A collection of nicknames for the person.
/// </summary>
/// <seealso cref="AdditionalNames"/>
/// <seealso cref="FamilyName"/>
/// <seealso cref="FormattedName"/>
/// <seealso cref="GivenName"/>
public StringCollection Nicknames
{
get
{
return this.nicknames;
}
}
/// <summary>
/// A collection of notes or comments.
/// </summary>
public vCardNoteCollection Notes
{
get
{
return this.notes;
}
}
/// <summary>
/// The office of the person at the organization.
/// </summary>
/// <seealso cref="Department"/>
/// <seealso cref="Organization"/>
public string Office
{
get
{
return this.office ?? string.Empty;
}
set
{
this.office = value;
}
}
/// <summary>
/// The organization or company of the person.
/// </summary>
/// <seealso cref="Office"/>
/// <seealso cref="Role"/>
/// <seealso cref="Title"/>
public string Organization
{
get
{
return this.organization ?? string.Empty;
}
set
{
this.organization = value;
}
}
/// <summary>
/// A collection of telephone numbers.
/// </summary>
public vCardPhoneCollection Phones
{
get
{
return this.phones;
}
}
/// <summary>
/// A collection of photographic images embedded or
/// referenced by the vCard.
/// </summary>
public vCardPhotoCollection Photos
{
get
{
return this.photos;
}
}
/// <summary>
/// The name of the product that generated the vCard.
/// </summary>
public string ProductId
{
get
{
return this.productId ?? string.Empty;
}
set
{
this.productId = value;
}
}
/// <summary>
/// The revision date of the vCard.
/// </summary>
/// <remarks>
/// The revision date is not automatically updated by the
/// vCard when modifying properties. It is up to the
/// developer to change the revision date as needed.
/// </remarks>
public DateTime? RevisionDate
{
get
{
return this.revisionDate;
}
set
{
this.revisionDate = value;
}
}
/// <summary>
/// The role of the person (e.g. Executive).
/// </summary>
/// <remarks>
/// The role is shown as "Profession" in Microsoft Outlook.
/// </remarks>
/// <seealso cref="Department"/>
/// <seealso cref="Office"/>
/// <seealso cref="Organization"/>
/// <seealso cref="Title"/>
public string Role
{
get
{
return this.role ?? string.Empty;
}
set
{
this.role = value;
}
}
/// <summary>
/// Directory sources for the vCard information.
/// </summary>
/// <remarks>
/// A vCard may contain zero or more sources. A source
/// identifies a directory that contains (or provided)
/// information found in the vCard. A program can
/// hypothetically connect to the source in order to
/// obtain updated information.
/// </remarks>
public vCardSourceCollection Sources
{
get
{
return this.sources;
}
}
/// <summary>
/// A string identifying the time zone of the entity
/// represented by the vCard.
/// </summary>
public string TimeZone
{
get
{
return this.timeZone ?? string.Empty;
}
set
{
this.timeZone = value;
}
}
/// <summary>
/// The job title of the person.
/// </summary>
/// <seealso cref="Organization"/>
/// <seealso cref="Role"/>
public string Title
{
get
{
return this.title ?? string.Empty;
}
set
{
this.title = value;
}
}
/// <summary>
/// Builds a string that represents the vCard.
/// </summary>
/// <returns>
/// The formatted name of the contact person, if defined,
/// or the default object.ToString().
/// </returns>
public override string ToString()
{
if (string.IsNullOrEmpty(this.formattedName))
{
return base.ToString();
}
else
{
return this.formattedName;
}
}
/// <summary>
/// A value that uniquely identifies the vCard.
/// </summary>
/// <remarks>
/// This value is optional. The string must be any string
/// that can be used to uniquely identify the vCard. The
/// usage of the field is determined by the software. Typical
/// possibilities for a unique string include a URL, a GUID,
/// or an LDAP directory path. However, there is no particular
/// standard dictated by the vCard specification.
/// </remarks>
public string UniqueId
{
get
{
return this.uniqueId ?? string.Empty;
}
set
{
this.uniqueId = value;
}
}
/// <summary>
/// Web sites associated with the person.
/// </summary>
/// <seealso cref="vCardWebsite"/>
/// <seealso cref="vCardWebsiteCollection"/>
public vCardWebsiteCollection Websites
{
get
{
return this.websites;
}
}
}
}

View File

@@ -0,0 +1,44 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// The access classification of a vCard.
/// </summary>
/// <remarks>
/// The access classification defines the intent of the vCard owner.
/// </remarks>
public enum vCardAccessClassification
{
/// <summary>
/// The vCard classification is unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// The vCard is classified as public.
/// </summary>
Public,
/// <summary>
/// The vCard is classified as private.
/// </summary>
Private,
/// <summary>
/// The vCard is classified as confidential.
/// </summary>
Confidential
}
}

View File

@@ -0,0 +1,125 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Security.Cryptography.X509Certificates;
namespace Thought.vCards
{
/// <summary>
/// A certificate attached to a vCard.
/// </summary>
/// <remarks>
/// <para>
/// A vCard can be associated with a public key or
/// authentication certificate. This is typically
/// a public X509 certificate that allows people to
/// use the key for validating messages.
/// </para>
/// </remarks>
[Serializable]
public class vCardCertificate
{
private string keyType;
private byte[] data;
/// <summary>
/// Creates a new instance of the <see cref="vCardCertificate"/> class.
/// </summary>
public vCardCertificate()
{
this.keyType = string.Empty;
}
/// <summary>
/// Creates a new instance of the <see cref="vCardCertificate"/>
/// class using the specified key type and raw certificate data.
/// </summary>
/// <param name="keyType">
/// A string that identifies the type of certificate,
/// such as X509.
/// </param>
/// <param name="data">
/// The raw certificate data stored as a byte array.
/// </param>
public vCardCertificate(string keyType, byte[] data)
{
if (string.IsNullOrEmpty(keyType))
throw new ArgumentNullException("keyType");
if (data == null)
throw new ArgumentNullException("data");
this.keyType = keyType;
this.data = data;
}
/// <summary>
/// Creates a vCard certificate based on an X509 certificate.
/// </summary>
/// <param name="x509">
/// An initialized X509 certificate.
/// </param>
public vCardCertificate(X509Certificate2 x509)
{
if (x509 == null)
throw new ArgumentNullException("x509");
this.data = x509.RawData;
this.keyType = "X509";
}
/// <summary>
/// The raw data of the certificate as a byte array.
/// </summary>
/// <remarks>
/// Most certificates consist of 8-bit binary data
/// that is encoded into a text format using BASE64
/// or a similar system. This property provides
/// access to the computer-friendly, decoded data.
/// </remarks>
public byte[] Data
{
get
{
return this.data;
}
set
{
this.data = value;
}
}
/// <summary>
/// A short string that identifies the type of certificate.
/// </summary>
/// <remarks>
/// The most common type is X509.
/// </remarks>
public string KeyType
{
get
{
return this.keyType ?? string.Empty;
}
set
{
this.keyType = value;
}
}
}
}

View File

@@ -0,0 +1,21 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardCertificate"/> objects.
/// </summary>
public class vCardCertificateCollection : Collection<vCardCertificate>
{
}
}

View File

@@ -0,0 +1,22 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A generic collection of <see cref="vCard"/> objects.
/// </summary>
public class vCardCollection : Collection<vCard>
{
}
}

View File

@@ -0,0 +1,286 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// A postal address.
/// </summary>
/// <seealso cref="vCardDeliveryAddressCollection"/>
[Serializable]
public class vCardDeliveryAddress
{
private vCardDeliveryAddressTypes addressType;
private string city;
private string country;
private string postalCode;
private string region;
private string street;
/// <summary>
/// Creates a new delivery address object.
/// </summary>
public vCardDeliveryAddress()
{
this.city = string.Empty;
this.country = string.Empty;
this.postalCode = string.Empty;
this.region = string.Empty;
this.street = string.Empty;
}
/// <summary>
/// The type of postal address.
/// </summary>
public vCardDeliveryAddressTypes AddressType
{
get
{
return this.addressType;
}
set
{
this.addressType = value;
}
}
/// <summary>
/// The city or locality of the address.
/// </summary>
public string City
{
get
{
return this.city ?? string.Empty;
}
set
{
this.city = value;
}
}
/// <summary>
/// The country name of the address.
/// </summary>
public string Country
{
get
{
return this.country ?? string.Empty;
}
set
{
this.country = value;
}
}
/// <summary>
/// Indicates a domestic delivery address.
/// </summary>
public bool IsDomestic
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Domestic) ==
vCardDeliveryAddressTypes.Domestic;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Domestic;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Domestic;
}
}
}
/// <summary>
/// Indicates a home address.
/// </summary>
public bool IsHome
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Home) ==
vCardDeliveryAddressTypes.Home;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Home;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Home;
}
}
}
/// <summary>
/// Indicates an international address.
/// </summary>
public bool IsInternational
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.International) ==
vCardDeliveryAddressTypes.International;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.International;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.International;
}
}
}
/// <summary>
/// Indicates a parcel delivery address.
/// </summary>
public bool IsParcel
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Parcel) ==
vCardDeliveryAddressTypes.Parcel;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Parcel;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Parcel;
}
}
}
/// <summary>
/// Indicates a postal address.
/// </summary>
public bool IsPostal
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Postal) ==
vCardDeliveryAddressTypes.Postal;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Postal;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Postal;
}
}
}
/// <summary>
/// Indicates a work address.
/// </summary>
public bool IsWork
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Work) ==
vCardDeliveryAddressTypes.Work;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Work;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Work;
}
}
}
/// <summary>
/// The postal code (e.g. ZIP code) of the address.
/// </summary>
public string PostalCode
{
get
{
return this.postalCode ?? string.Empty;
}
set
{
this.postalCode = value;
}
}
/// <summary>
/// The region (state or province) of the address.
/// </summary>
public string Region
{
get
{
return this.region ?? string.Empty;
}
set
{
this.region = value;
}
}
/// <summary>
/// The street of the delivery address.
/// </summary>
public string Street
{
get
{
return this.street ?? string.Empty;
}
set
{
this.street = value;
}
}
}
}

View File

@@ -0,0 +1,22 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardDeliveryAddress"/> objects.
/// </summary>
/// <seealso cref="vCardDeliveryAddress"/>
public class vCardDeliveryAddressCollection : Collection<vCardDeliveryAddress>
{
}
}

View File

@@ -0,0 +1,56 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// The type of a delivery address.
/// </summary>
[Flags]
public enum vCardDeliveryAddressTypes
{
/// <summary>
/// Default address settings.
/// </summary>
Default = 0,
/// <summary>
/// A domestic delivery address.
/// </summary>
Domestic,
/// <summary>
/// An international delivery address.
/// </summary>
International,
/// <summary>
/// A postal delivery address.
/// </summary>
Postal,
/// <summary>
/// A parcel delivery address.
/// </summary>
Parcel,
/// <summary>
/// A home delivery address.
/// </summary>
Home,
/// <summary>
/// A work delivery address.
/// </summary>
Work
}
}

View File

@@ -0,0 +1,228 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// A formatted delivery label.
/// </summary>
/// <seealso cref="vCardDeliveryAddress"/>
/// <seealso cref="vCardDeliveryLabelCollection"/>
public class vCardDeliveryLabel
{
private vCardDeliveryAddressTypes addressType;
private string text;
/// <summary>
/// Initializes a new <see cref="vCardDeliveryLabel"/>.
/// </summary>
public vCardDeliveryLabel()
{
}
/// <summary>
/// Initializes a new <see cref="vCardDeliveryLabel"/> to
/// the specified text.
/// </summary>
/// <param name="text">
/// The formatted text of a delivery label. The label
/// may contain carriage returns, line feeds, and other
/// control characters.
/// </param>
public vCardDeliveryLabel(string text)
{
this.text = text == null ? string.Empty : text;
}
/// <summary>
/// The type of delivery address for the label.
/// </summary>
public vCardDeliveryAddressTypes AddressType
{
get
{
return this.addressType;
}
set
{
this.addressType = value;
}
}
/// <summary>
/// Indicates a domestic delivery address.
/// </summary>
public bool IsDomestic
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Domestic) ==
vCardDeliveryAddressTypes.Domestic;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Domestic;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Domestic;
}
}
}
/// <summary>
/// Indicates a home address.
/// </summary>
public bool IsHome
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Home) ==
vCardDeliveryAddressTypes.Home;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Home;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Home;
}
}
}
/// <summary>
/// Indicates an international address.
/// </summary>
public bool IsInternational
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.International) ==
vCardDeliveryAddressTypes.International;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.International;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.International;
}
}
}
/// <summary>
/// Indicates a parcel delivery address.
/// </summary>
public bool IsParcel
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Parcel) ==
vCardDeliveryAddressTypes.Parcel;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Parcel;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Parcel;
}
}
}
/// <summary>
/// Indicates a postal address.
/// </summary>
public bool IsPostal
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Postal) ==
vCardDeliveryAddressTypes.Postal;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Postal;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Postal;
}
}
}
/// <summary>
/// Indicates a work address.
/// </summary>
public bool IsWork
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Work) ==
vCardDeliveryAddressTypes.Work;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Work;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Work;
}
}
}
/// <summary>
/// The formatted delivery text.
/// </summary>
public string Text
{
get
{
return this.text ?? string.Empty;
}
set
{
this.text = value;
}
}
}
}

View File

@@ -0,0 +1,21 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardDeliveryLabel"/> objects.
/// </summary>
public class vCardDeliveryLabelCollection : Collection<vCardDeliveryLabel>
{
}
}

View File

@@ -0,0 +1,131 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// An email address in a <see cref="vCard"/>.
/// </summary>
/// <remarks>
/// Most vCard email addresses are Internet email addresses. However,
/// the vCard specification allows other email address formats,
/// such as CompuServe and X400. Unless otherwise specified, an
/// address is assumed to be an Internet address.
/// </remarks>
/// <seealso cref="vCardEmailAddressCollection"/>
/// <seealso cref="vCardEmailAddressType"/>
public class vCardEmailAddress
{
private string address;
private vCardEmailAddressType emailType;
private bool isPreferred;
/// <summary>
/// Creates a new <see cref="vCardEmailAddress"/>.
/// </summary>
public vCardEmailAddress()
{
this.address = string.Empty;
this.emailType = vCardEmailAddressType.Internet;
}
/// <summary>
/// Creates a new Internet <see cref="vCardEmailAddress"/>.
/// </summary>
/// <param name="address">
/// The Internet email address.
/// </param>
public vCardEmailAddress(string address)
{
this.address = address == null ? string.Empty : address;
this.emailType = vCardEmailAddressType.Internet;
}
/// <summary>
/// Creates a new <see cref="vCardEmailAddress"/> of the specified type.
/// </summary>
/// <param name="address">
/// The email address.
/// </param>
/// <param name="emailType">
/// The type of email address.
/// </param>
public vCardEmailAddress(string address, vCardEmailAddressType emailType)
{
this.address = address;
this.emailType = emailType;
}
/// <summary>
/// The email address.
/// </summary>
/// <remarks>
/// The format of the email address is not validated by the class.
/// </remarks>
public string Address
{
get
{
return this.address ?? string.Empty;
}
set
{
this.address = value;
}
}
/// <summary>
/// The email address type.
/// </summary>
public vCardEmailAddressType EmailType
{
get
{
return this.emailType;
}
set
{
this.emailType = value;
}
}
/// <summary>
/// Indicates a preferred (top priority) email address.
/// </summary>
public bool IsPreferred
{
get
{
return this.isPreferred;
}
set
{
this.isPreferred = value;
}
}
/// <summary>
/// Builds a string that represents the email address.
/// </summary>
public override string ToString()
{
return this.address;
}
}
}

View File

@@ -0,0 +1,70 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardEmailAddress"/> objects.
/// </summary>
/// <seealso cref="vCardEmailAddress"/>
/// <seealso cref="vCardEmailAddressType"/>
public class vCardEmailAddressCollection : Collection<vCardEmailAddress>
{
/// <summary>
/// Initializes a new instance of the <see cref="vCardEmailAddressCollection" />.
/// </summary>
public vCardEmailAddressCollection()
: base()
{
}
/// <summary>
/// Locates the first email address of the specified type while
/// giving preference to email addresses marked as preferred.
/// </summary>
/// <param name="emailType">
/// The type of email address to locate. This can be any
/// combination of values from <see cref="vCardEmailAddressType"/>.
/// </param>
/// <returns>
/// The function returns the first preferred email address that matches
/// the specified type. If the collection does not contain a preferred
/// email address, then it will return the first non-preferred matching
/// email address. The function returns null if no matches were found.
/// </returns>
public vCardEmailAddress GetFirstChoice(vCardEmailAddressType emailType)
{
vCardEmailAddress firstNonPreferred = null;
foreach (vCardEmailAddress email in this)
{
if ((email.EmailType & emailType) == emailType)
{
if (firstNonPreferred == null)
firstNonPreferred = email;
if (email.IsPreferred)
return email;
}
}
return firstNonPreferred;
}
}
}

View File

@@ -0,0 +1,97 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// Identifies the type of email address in a vCard.
/// </summary>
/// <seealso cref="vCardEmailAddress"/>
public enum vCardEmailAddressType
{
/// <summary>
/// An Internet (SMTP) mail (default) address.
/// </summary>
Internet = 0,
/// <summary>
/// An America On-Line email address.
/// </summary>
AOL,
/// <summary>
/// An AppleLink email address.
/// </summary>
AppleLink,
/// <summary>
/// An AT&amp;T Mail email address
/// </summary>
AttMail,
/// <summary>
/// A CompuServe Information Service (CIS) email address.
/// </summary>
CompuServe,
/// <summary>
/// An eWorld email address.
/// </summary>
/// <remarks>
/// eWorld was an online service by Apple Computer in the mid 1990s.
/// It was officially shut down on March 31, 1996.
/// </remarks>
eWorld,
/// <summary>
/// An IBM Mail email address.
/// </summary>
IBMMail,
/// <summary>
/// An MCI Mail email address.
/// </summary>
MCIMail,
/// <summary>
/// A PowerShare email address.
/// </summary>
PowerShare,
/// <summary>
/// A Prodigy Information Service email address.
/// </summary>
Prodigy,
/// <summary>
/// A telex email address.
/// </summary>
Telex,
/// <summary>
/// An X.400 service email address.
/// </summary>
X400
}
}

View File

@@ -0,0 +1,41 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// The encoding used to store a vCard property value in text format.
/// </summary>
public enum vCardEncoding
{
/// <summary>
/// Unknown or no encoding.
/// </summary>
Unknown = 0,
/// <summary>
/// Standard escaped text.
/// </summary>
Escaped,
/// <summary>
/// Binary or BASE64 encoding.
/// </summary>
Base64,
/// <summary>
/// Quoted-Printable encoding.
/// </summary>
QuotedPrintable
}
}

View File

@@ -0,0 +1,66 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// Base class for <see cref="vCard"/>-specific exceptions.
/// </summary>
[Serializable]
public class vCardException : Exception
{
/// <summary>
/// Initializes a new instance of the vCardException class.
/// </summary>
public vCardException()
: base()
{
}
/// <summary>
/// Initializes a new instance of the vCardException
/// class with the specified error message.
/// </summary>
/// <param name="message">
/// The message that describes the error.
/// </param>
public vCardException(string message)
: base(message)
{
}
/// <summary>
/// Initializes a new instance of the vCardException
/// class with a specified error message and a reference
/// to the inner exception that is the cause of the
/// exception.
/// </summary>
/// <param name="message">
/// The error message that explains the reason for the exception.
/// </param>
/// <param name="innerException">
/// The exception that is the cause of the current exception,
/// or a null reference (Nothing in Visual Basic) if no
/// inner exception is specified.
/// </param>
public vCardException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

View File

@@ -0,0 +1,43 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// Identifies different vCard formats.
/// </summary>
public enum vCardFormat
{
/// <summary>
/// Standard text format.
/// </summary>
Text,
/// <summary>
/// Jabber XML format (not implemented yet).
/// </summary>
JabberXml,
/// <summary>
/// RDF format (not implemented yet).
/// </summary>
Rdf,
/// <summary>
/// hCard microformat (not implemented yet).
/// </summary>
hCard
}
}

View File

@@ -0,0 +1,47 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// The gender (male or female) of the contact.
/// </summary>
/// <remarks>
/// <para>
/// Gender is not directly supported by the vCard specification.
/// It is recognized by Microsoft Outlook and the Windows Address
/// Book through an extended property called X-WAB-GENDER. This
/// property has a value of 1 for women and 2 for men.
/// </para>
/// </remarks>
/// <seealso cref="vCard.Gender"/>
public enum vCardGender
{
/// <summary>
/// Unknown gender.
/// </summary>
Unknown = 0,
/// <summary>
/// Female gender.
/// </summary>
Female = 1,
/// <summary>
/// Male gender.
/// </summary>
Male = 2
}
}

View File

@@ -0,0 +1,82 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
namespace Thought.vCards
{
/// <summary>
/// A note or comment in a vCard.
/// </summary>
public class vCardNote
{
private string language;
private string text;
/// <summary>
/// Initializes a new vCard note.
/// </summary>
public vCardNote()
{
}
/// <summary>
/// Initializes a new vCard note with the specified text.
/// </summary>
/// <param name="text">
/// The text of the note or comment.
/// </param>
public vCardNote(string text)
{
this.text = text;
}
/// <summary>
/// The language of the note.
/// </summary>
public string Language
{
get
{
return this.language ?? string.Empty;
}
set
{
this.language = value;
}
}
/// <summary>
/// The text of the note.
/// </summary>
public string Text
{
get
{
return this.text ?? string.Empty;
}
set
{
this.text = value;
}
}
/// <summary>
/// Returns the text of the note.
/// </summary>
public override string ToString()
{
return this.text ?? string.Empty;
}
}
}

View File

@@ -0,0 +1,48 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardNote"/> objects.
/// </summary>
public class vCardNoteCollection : Collection<vCardNote>
{
/// <summary>
/// Initializes a new instance of the <see cref="vCardNoteCollection"/>.
/// </summary>
public vCardNoteCollection()
: base()
{
}
/// <summary>
/// Adds a new note to the collection.
/// </summary>
/// <param name="text">
/// The text of the note.
/// </param>
/// <returns>
/// The <see cref="vCardNote"/> object representing the note.
/// </returns>
public vCardNote Add(string text)
{
vCardNote note = new vCardNote(text);
Add(note);
return note;
}
}
}

View File

@@ -0,0 +1,411 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// Telephone information for a <see cref="vCard"/>.
/// </summary>
/// <seealso cref="vCardPhoneCollection"/>
/// <seealso cref="vCardPhoneTypes"/>
[Serializable]
public class vCardPhone
{
private string fullNumber;
private vCardPhoneTypes phoneType;
/// <summary>
/// Creates a new <see cref="vCardPhone"/> object.
/// </summary>
public vCardPhone()
{
}
/// <summary>
/// Creates a new <see cref="vCardPhone"/> object with the specified number.
/// </summary>
/// <param name="fullNumber">
/// The phone number.
/// </param>
public vCardPhone(string fullNumber)
{
this.fullNumber = fullNumber;
}
/// <summary>
/// Creates a new <see cref="vCardPhone"/> with the specified number and subtype.
/// </summary>
/// <param name="fullNumber">The phone number.</param>
/// <param name="phoneType">The phone subtype.</param>
public vCardPhone(string fullNumber, vCardPhoneTypes phoneType)
{
this.fullNumber = fullNumber;
this.phoneType = phoneType;
}
/// <summary>
/// The full telephone number.
/// </summary>
public string FullNumber
{
get
{
return this.fullNumber ?? string.Empty;
}
set
{
this.fullNumber = value;
}
}
/// <summary>
/// Indicates a BBS number.
/// </summary>
/// <seealso cref="IsModem"/>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsBBS
{
get
{
return (this.phoneType & vCardPhoneTypes.BBS) == vCardPhoneTypes.BBS;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.BBS;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.BBS;
}
}
}
/// <summary>
/// Indicates a car number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsCar
{
get
{
return (this.phoneType & vCardPhoneTypes.Car) == vCardPhoneTypes.Car;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Car;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Car;
}
}
}
/// <summary>
/// Indicates a cellular number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsCellular
{
get
{
return (this.phoneType & vCardPhoneTypes.Cellular) == vCardPhoneTypes.Cellular;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Cellular;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Cellular;
}
}
}
/// <summary>
/// Indicates a fax number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsFax
{
get
{
return (this.phoneType & vCardPhoneTypes.Fax) == vCardPhoneTypes.Fax;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Fax;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Fax;
}
}
}
/// <summary>
/// Indicates a home number.
/// </summary>
/// <seealso cref="IsWork"/>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsHome
{
get
{
return (this.phoneType & vCardPhoneTypes.Home) == vCardPhoneTypes.Home;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Home;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Home;
}
}
}
/// <summary>
/// Indicates an ISDN number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsISDN
{
get
{
return (this.phoneType & vCardPhoneTypes.ISDN) == vCardPhoneTypes.ISDN;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.ISDN;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.ISDN;
}
}
}
/// <summary>
/// Indicates a messaging service number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsMessagingService
{
get
{
return (this.phoneType & vCardPhoneTypes.MessagingService) ==
vCardPhoneTypes.MessagingService;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.MessagingService;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.MessagingService;
}
}
}
/// <summary>
/// Indicates a modem number.
/// </summary>
/// <seealso cref="IsBBS"/>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsModem
{
get
{
return (this.phoneType & vCardPhoneTypes.Modem) == vCardPhoneTypes.Modem;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Modem;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Modem;
}
}
}
/// <summary>
/// Indicates a pager number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsPager
{
get
{
return (this.phoneType & vCardPhoneTypes.Pager) == vCardPhoneTypes.Pager;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Pager;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Pager;
}
}
}
/// <summary>
/// Indicates a preferred number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsPreferred
{
get
{
return (this.phoneType & vCardPhoneTypes.Preferred) == vCardPhoneTypes.Preferred;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Preferred;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Preferred;
}
}
}
/// <summary>
/// Indicates a video number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsVideo
{
get
{
return (this.phoneType & vCardPhoneTypes.Video) == vCardPhoneTypes.Video;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Video;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Video;
}
}
}
/// <summary>
/// Indicates a voice number.
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsVoice
{
get
{
return (this.phoneType & vCardPhoneTypes.Voice) == vCardPhoneTypes.Voice;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Voice;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Voice;
}
}
}
/// <summary>
/// Indicates a work number.
/// </summary>
/// <seealso cref="IsHome"/>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsWork
{
get
{
return (this.phoneType & vCardPhoneTypes.Work) == vCardPhoneTypes.Work;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Work;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Work;
}
}
}
/// <summary>
/// The phone subtype.
/// </summary>
/// <seealso cref="IsVideo"/>
/// <seealso cref="IsVoice"/>
/// <seealso cref="IsWork"/>
public vCardPhoneTypes PhoneType
{
get
{
return this.phoneType;
}
set
{
this.phoneType = value;
}
}
}
}

View File

@@ -0,0 +1,67 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A generic collection <see cref="vCardPhone"/> objects.
/// </summary>
/// <seealso cref="vCardPhone"/>
/// <seealso cref="vCardPhoneTypes"/>
public class vCardPhoneCollection : Collection<vCardPhone>
{
/// <summary>
/// Looks for the first phone of the specified
/// type that is a preferred phone.
/// </summary>
/// <param name="phoneType">
/// The type of phone to seek.
/// </param>
/// <returns>
/// The first <see cref="vCardPhone "/> that matches
/// the specified type. A preferred number is returned
/// before a non-preferred number.
/// </returns>
public vCardPhone GetFirstChoice(vCardPhoneTypes phoneType)
{
vCardPhone firstNonPreferred = null;
foreach (vCardPhone phone in this)
{
if ((phone.PhoneType & phoneType) == phoneType)
{
// This phone has the same phone type as
// specified by the caller. Save a reference
// to the first such phone encountered.
if (firstNonPreferred == null)
firstNonPreferred = phone;
if (phone.IsPreferred)
return phone;
}
}
// No phone had the specified phone type and was marked
// as preferred.
return firstNonPreferred;
}
}
}

View File

@@ -0,0 +1,113 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// Identifies different phone types (e.g. Fax, BBS, etc).
/// </summary>
/// <seealso cref="vCardPhone"/>
/// <seealso cref="vCardPhoneCollection"/>
[Flags]
public enum vCardPhoneTypes
{
/// <summary>
/// Indicates default properties.
/// </summary>
Default = 0,
/// <summary>
/// Indicates a bulletin board system.
/// </summary>
BBS = 1,
/// <summary>
/// Indicates a car phone.
/// </summary>
Car = 2,
/// <summary>
/// Indicates a cell phone.
/// </summary>
Cellular = 4,
/// <summary>
/// Indicates a celluar voice number.
/// </summary>
CellularVoice = Cellular + Voice,
/// <summary>
/// Indicates a facsimile number.
/// </summary>
Fax = 8,
/// <summary>
/// Indicates a home number
/// </summary>
Home = 16,
/// <summary>
/// Indicates a home and voice number.
/// </summary>
HomeVoice = Home + Voice,
/// <summary>
/// Indicates an ISDN number.
/// </summary>
ISDN = 32,
/// <summary>
/// Indicates a messaging service on the number.
/// </summary>
MessagingService = 64,
/// <summary>
/// Indicates a MODEM number.
/// </summary>
Modem = 128,
/// <summary>
/// Indicates a pager number.
/// </summary>
Pager = 256,
/// <summary>
/// Indicates a preferred number.
/// </summary>
Preferred = 512,
/// <summary>
/// Indicates a video number.
/// </summary>
Video = 1024,
/// <summary>
/// Indicates a voice number.
/// </summary>
Voice = 2048,
/// <summary>
/// Indicates a work number.
/// </summary>
Work = 4096,
/// <summary>
/// Indicates a work fax number.
/// </summary>
WorkFax = Work + Fax,
/// <summary>
/// Indicates a work and voice number.
/// </summary>
WorkVoice = Work + Voice
}
}

View File

@@ -0,0 +1,279 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Drawing;
using System.IO;
using System.Net;
namespace Thought.vCards
{
/// <summary>
/// A photo embedded in a vCard.
/// </summary>
/// <remarks>
/// <para>
/// You must specify the photo using a path, a byte array,
/// or a System.Drawing.Bitmap instance. The class will
/// extract the underlying raw bytes for storage into the
/// vCard. You can call the <see cref="GetBitmap"/> function
/// to create a new Windows bitmap object (e.g. for display
/// on a form) or <see cref="GetBytes"/> to extract the raw
/// bytes (e.g. for transmission from a web page).
/// </para>
/// </remarks>
[Serializable]
public class vCardPhoto
{
/// <summary>
/// The raw bytes of the image data.
/// </summary>
/// <remarks>
/// The raw bytes can be passed directly to the photo object
/// or fetched from a file or remote URL. A .NET bitmap object
/// can also be specified, in which case the constructor
/// will load the raw bytes from the bitmap.
/// </remarks>
private byte[] data;
/// <summary>
/// The url of the image.
/// </summary>
private Uri url;
/// <summary>
/// Loads a photograph from an array of bytes.
/// </summary>
/// <param name="buffer">
/// An array of bytes containing the raw data from
/// any of the supported image formats.
/// </param>
public vCardPhoto(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
this.data = (byte[])buffer.Clone();
}
/// <summary>
/// The URL of the image.
/// </summary>
/// <param name="url">
/// A URL pointing to an image.
/// </param>
public vCardPhoto(Uri url)
{
if (url == null)
throw new ArgumentNullException("url");
this.url = url;
}
/// <summary>
/// Creates a new vCard photo from an image file.
/// </summary>
/// <param name="path">
/// The path to an image of any supported format.
/// </param>
public vCardPhoto(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException("path");
this.url = new Uri(path);
}
/// <summary>
/// Creates a new vCard photo from an existing Bitmap object.
/// </summary>
/// <param name="bitmap">
/// A bitmap to be attached to the vCard as a photo.
/// </param>
public vCardPhoto(Bitmap bitmap)
{
if (bitmap == null)
throw new ArgumentNullException("bitmap");
// Extract the raw bytes of the bitmap
// to a stream.
MemoryStream bytes = new MemoryStream();
bitmap.Save(bytes, bitmap.RawFormat);
// Extract the bytes of the stream to the array.
bytes.Seek(0, SeekOrigin.Begin);
bytes.Read(data, 0, (int)bytes.Length);
}
/// <summary>
/// Fetches a linked image asynchronously.
/// </summary>
/// <remarks>
/// This is a simple utility method for accessing the image
/// referenced by the URL. For asynchronous or advanced
/// loading you will need to download the image yourself
/// and load the bytes directly into the class.
/// </remarks>
/// <seealso cref="IsLoaded"/>
/// <seealso cref="Url"/>
public void Fetch()
{
// An image can be fetched only if the URL
// of the image is known. Otherwise the
// fetch operation makes no sense.
if (this.url == null)
throw new InvalidOperationException();
// Create a web request object that will handle the
// specifics of downloading a file from the specified
// URL. For example, the URL is a file-based URL, then
// the CreateDefault method will return a FileWebRequest
// class.
WebRequest request =
WebRequest.CreateDefault(this.url);
// Start the request. The request begins when
// the GetResponse method is invoked. This is a
// synchronous (blocking) call (i.e. it will not
// return until the file is downloaded or an
// exception is raised).
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
// Allocate space to hold the entire image.
this.data = new byte[response.ContentLength];
// The following call will fail if the image
// size is larger than the capacity of an Int32.
// This may be treated as a minor issue given
// the fact that this is a vCard library and
// such images are expected by humans to be small.
// No reasonable person would embed a multi-gigabyte
// image into a vCard.
responseStream.Read(
this.data,
0,
(int)response.ContentLength);
}
}
/// <summary>
/// Creates a Bitmap object from the photo data.
/// </summary>
/// <remarks>
/// An initialized Bitmap object. An exception is
/// raised if the .NET framework is unable to identify
/// the format of the image data, or if the format
/// is not supported.
/// </remarks>
public Bitmap GetBitmap()
{
MemoryStream stream = new MemoryStream(this.data);
return new Bitmap(stream);
}
/// <summary>
/// Returns a copy of the raw bytes of the image.
/// </summary>
/// <returns>
/// A byte array containing the raw bytes of the image.
/// </returns>
/// <remarks>
/// A copy of the raw bytes are returned. Modifying the
/// array will not modify the photo.
/// </remarks>
public byte[] GetBytes()
{
return (byte[])this.data.Clone();
}
/// <summary>
/// Indicates the bytes of the raw image have
/// been loaded by the object.
/// </summary>
/// <seealso cref="Fetch"/>
public bool IsLoaded
{
get
{
return this.data != null;
}
}
/// <summary>
/// The URL of the image.
/// </summary>
/// <remarks>
/// Changing the URL will automatically invalidate the internal
/// image data if previously fetched.
/// </remarks>
/// <seealso cref="Fetch"/>
public Uri Url
{
get
{
return this.url;
}
set
{
// This class maintains a byte array containing the raw
// bytes of the image. The use can call the Fetch method
// to load the raw bytes from a remote link. If the
// URL is changed (e.g. via this property), then the local
// cache must be invalidated.
if (value == null)
{
this.data = null;
this.url = null;
}
else
{
if (this.url != value)
{
this.data = null;
this.url = value;
}
}
}
}
}
}

View File

@@ -0,0 +1,31 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardPhoto"/> objects.
/// </summary>
/// <seealso cref="vCardPhoto"/>
public class vCardPhotoCollection : Collection<vCardPhoto>
{
/// <summary>
/// Initializes a new instance of the <see cref="vCardPhotoCollection"/>.
/// </summary>
public vCardPhotoCollection()
: base()
{
}
}
}

View File

@@ -0,0 +1,258 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Text;
namespace Thought.vCards
{
/// <summary>
/// A property of a <see cref="vCard"/>.
/// </summary>
/// <remarks>
/// <para>
/// A vCard property specifies a single piece of information,
/// such as an email address or telephone number. A property
/// can also specify meta-data like a revision number. A full
/// vCards is basically a collection of properties structured
/// into a computer-friendly text format.
/// </para>
/// <para>
/// A property has a name, a value, and optionally one or
/// more subproperties. A subproperty provides additional
/// information about the property (such as the encoding
/// used to store the value). The format of a value
/// depends on the property and in some cases may be broken
/// into multiple values.
/// </para>
/// </remarks>
/// <seealso cref="vCardPropertyCollection"/>
public class vCardProperty
{
private string group;
private string language;
private string name;
private vCardSubpropertyCollection subproperties;
private object value;
/// <summary>
/// Creates a blank <see cref="vCardProperty"/> object.
/// </summary>
public vCardProperty()
{
this.subproperties = new vCardSubpropertyCollection();
}
/// <summary>
/// Creates a <see cref="vCardProperty"/> object
/// with the specified name and a null value.
/// </summary>
/// <param name="name">
/// The name of the property.
/// </param>
public vCardProperty(string name)
{
this.name = name;
this.subproperties = new vCardSubpropertyCollection();
}
/// <summary>
/// Creates a <see cref="vCardProperty"/> object with the
/// specified name and value.
/// </summary>
/// <remarks>
/// The vCard specification supports multiple values in
/// certain fields, such as the N field. The value specified
/// in this constructor is loaded as the first value.
/// </remarks>
public vCardProperty(string name, string value)
{
this.name = name;
this.subproperties = new vCardSubpropertyCollection();
this.value = value;
}
/// <summary>
/// Initializes a vCardProperty with the specified
/// name, value and group.
/// </summary>
/// <param name="name">
/// The name of the vCard property.
/// </param>
/// <param name="value">
/// The value of the vCard property.
/// </param>
/// <param name="group">
/// The group name of the vCard property.
/// </param>
public vCardProperty(string name, string value, string group)
{
this.group = group;
this.name = name;
this.subproperties = new vCardSubpropertyCollection();
this.value = value;
}
/// <summary>
/// Creates a <see cref="vCardProperty"/> with the
/// specified name and a byte array as a value.
/// </summary>
/// <param name="name">The name of the property.</param>
/// <param name="value">The value as a byte array.</param>
public vCardProperty(string name, byte[] value)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
this.name = name;
this.subproperties = new vCardSubpropertyCollection();
this.value = value;
}
/// <summary>
/// Creates a <see cref="vCardProperty"/> with
/// the specified name and date/time as a value.
/// </summary>
/// <param name="name">The name of the property.</param>
/// <param name="value">The date/time value.</param>
public vCardProperty(string name, DateTime value)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
this.name = name;
this.subproperties = new vCardSubpropertyCollection();
this.value = value;
}
/// <summary>
/// Initializes the vCard property with the specified
/// name and values.
/// </summary>
public vCardProperty(string name, vCardValueCollection values)
: this()
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (values == null)
throw new ArgumentNullException("values");
this.subproperties = new vCardSubpropertyCollection();
this.name = name;
this.value = values;
}
/// <summary>
/// The group name of the property.
/// </summary>
public string Group
{
get
{
return this.group ?? string.Empty;
}
set
{
this.group = value;
}
}
/// <summary>
/// The language code of the property.
/// </summary>
public string Language
{
get
{
return this.language ?? string.Empty;
}
set
{
this.language = value;
}
}
/// <summary>
/// The name of the property (e.g. TEL).
/// </summary>
public string Name
{
get
{
return this.name ?? string.Empty;
}
set
{
this.name = value;
}
}
/// <summary>
/// Subproperties of the vCard property, not including
/// the name, encoding, and character set.
/// </summary>
public vCardSubpropertyCollection Subproperties
{
get
{
return this.subproperties;
}
}
/// <summary>
/// Returns the value of the property as a string.
/// </summary>
public override string ToString()
{
if (value == null)
{
return string.Empty;
}
else
{
return value.ToString();
}
}
/// <summary>
/// The value of the property.
/// </summary>
public object Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
}
}

View File

@@ -0,0 +1,22 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A generic collection of <see cref="vCardProperty"/> objects.
/// </summary>
/// <seealso cref="vCardProperty"/>
public class vCardPropertyCollection : Collection<vCardProperty>
{
}
}

View File

@@ -0,0 +1,94 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Specialized;
using System.IO;
namespace Thought.vCards
{
/// <summary>
/// An abstract reader for vCard and vCard-like file formats.
/// </summary>
/// <remarks>
/// <para>
/// The <see cref="Warnings"/> property is a string collection
/// containing a description of each warning encountered during
/// the read process. An implementor of a card reader should
/// populate this collection as the vCard data is being parsed.
/// </para>
/// </remarks>
public abstract class vCardReader
{
/// <summary>
/// Stores the warnings issued by the implementor
/// of the vCard reader. Currently warnings are
/// simple string messages; a future version will
/// store line numbers, severity levels, etc.
/// </summary>
/// <seealso cref="Warnings"/>
private StringCollection warnings;
/// <summary>
/// Initializes the base reader.
/// </summary>
protected vCardReader()
{
this.warnings = new StringCollection();
}
/// <summary>
/// Reads a vCard from the specified input stream.
/// </summary>
/// <param name="reader">
/// A text reader that points to the beginning of
/// a vCard in the format expected by the implementor.
/// </param>
/// <returns>
/// An initialized <see cref="vCard"/> object.
/// </returns>
public vCard Read(TextReader reader)
{
vCard card = new vCard();
ReadInto(card, reader);
return card;
}
/// <summary>
/// Reads vCard information from a text reader and
/// populates into an existing vCard object.
/// </summary>
/// <param name="card">
/// An initialized vCard object.
/// </param>
/// <param name="reader">
/// A text reader containing vCard data in the format
/// expected by the card reader class.
/// </param>
public abstract void ReadInto(vCard card, TextReader reader);
/// <summary>
/// A collection of warning messages.
/// </summary>
/// <remarks>Reseved for future use.</remarks>
public StringCollection Warnings
{
get
{
return this.warnings;
}
}
}
}

View File

@@ -0,0 +1,110 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// A source of directory information for a vCard.
/// </summary>
/// <remarks>
/// <para>
/// A source identifies a directory that contains or provided
/// information for the vCard. A source consists of a URI
/// and a context. The URI is generally a URL; the
/// context identifies the protocol and type of URI. For
/// example, a vCard associated with an LDAP directory entry
/// will have an ldap:// URL and a context of "LDAP".
/// </para>
/// </remarks>
/// <seealso cref="vCardSourceCollection"/>
public class vCardSource
{
private string context;
private Uri uri;
/// <summary>
/// Initializes a new instance of the vCardSource class.
/// </summary>
public vCardSource()
{
this.context = string.Empty;
}
/// <summary>
/// Initializes a new source with the specified URI.
/// </summary>
/// <param name="uri">
/// The URI of the directory entry.
/// </param>
public vCardSource(Uri uri)
{
this.uri = uri;
}
/// <summary>
/// Initializes a new source with the specified
/// context and URI.
/// </summary>
/// <param name="uri">
/// The URI of the source of the vCard data.
/// </param>
/// <param name="context">
/// The context of the source.
/// </param>
public vCardSource(Uri uri, string context)
{
this.context = context;
this.uri = uri;
}
/// <summary>
/// The context of the source URI.
/// </summary>
/// <remarks>
/// The context identifies how the URI should be
/// interpreted. Example is "LDAP", which indicates
/// the URI is an LDAP reference.
/// </remarks>
public string Context
{
get
{
return this.context ?? string.Empty;
}
set
{
this.context = value;
}
}
/// <summary>
/// The URI of the source.
/// </summary>
public Uri Uri
{
get
{
return this.uri;
}
set
{
this.uri = value;
}
}
}
}

View File

@@ -0,0 +1,31 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardSource"/> objects.
/// </summary>
/// <seealso cref="vCardSource"/>
public class vCardSourceCollection : Collection<vCardSource>
{
/// <summary>
/// Initializes a new instance of the <see cref="vCardSourceCollection"/>.
/// </summary>
public vCardSourceCollection()
: base()
{
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Generic;
using System.Text;
namespace Thought.vCards
{
/// <summary>
/// Extended options for the <see cref="vCardStandardWriter"/> class.
/// </summary>
[Flags]
public enum vCardStandardWriterOptions
{
/// <summary>
/// No options.
/// </summary>
None = 0,
/// <summary>
/// Indicates whether or not commas should be escaped in values.
/// </summary>
/// <remarks>
/// The vCard specification requires that commas be escaped
/// in values (e.g. a "," is translated to "\,"). However, Microsoft
/// Outlook(tm) does not properly decode these escaped commas. This
/// option instruct the writer to ignored (not translate) embedded
/// commas for better compatibility with Outlook.
/// </remarks>
IgnoreCommas = 1
}
}

View File

@@ -0,0 +1,141 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// A subproperty of a vCard property.
/// </summary>
/// <remarks>
/// <para>
/// A vCard is fundamentally a set of properties in NAME:VALUE
/// format, where the name is a keyword like "EMAIL" and the
/// value is a string appropriate for the keyword (e.g. an email
/// address for the EMAIL property, or a BASE64 encoded image
/// for the PHOTO property).
/// </para>
/// <para>
/// All vCard properties support subproperties. These can
/// be global options like encoding or value type, or might be
/// options specific to the keyword. For example, all vCard
/// properties can have an encoding subproperty that identifies
/// the text encoding of the value. A phone property, however,
/// supports special properties that identify the type and purpose
/// of the phone.
/// </para>
/// <para>
/// A subproperty is not required to have a value. In such a case
/// the subproperty acts like a flag. For example, the TEL
/// property of the vCard specification is used to indicate a
/// telephone number associated with the person. This property
/// supports a subproperty called BBS, which indicates the telephone
/// number is for a dial-up bulletin board system. The BBS
/// subproperty does not need a value; the existance of the BBS
/// subproperty is sufficient to indicate the telephone number is
/// for a BBS system.
/// </para>
/// </remarks>
public class vCardSubproperty
{
/// <summary>
/// Stores the name of the subproperty.
/// </summary>
private string name;
/// <summary>
/// Stores the value of the subproperty. This can be null.
/// </summary>
private string value;
/// <summary>
/// Creates a subproperty with the specified
/// name and no value.
/// </summary>
/// <param name="name">
/// The name of the subproperty.
/// </param>
public vCardSubproperty(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
else
{
this.name = name;
}
}
/// <summary>
/// Creates a subproperty with the specified
/// name and value.
/// </summary>
/// <param name="name">
/// The name of the subproperty.
/// </param>
/// <param name="value">
/// The value of the subproperty. This can be null.
/// </param>
public vCardSubproperty(string name, string value)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
else
{
this.name = name;
}
this.value = value;
}
/// <summary>
/// The name of the subproperty.
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
/// <summary>
/// The optional value of the subproperty.
/// </summary>
public string Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
}
}

View File

@@ -0,0 +1,368 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardSubproperty"/> objects.
/// </summary>
/// <remarks>
/// <para>
/// This class is a general-purpose collection of
/// <see cref="vCardSubproperty"/> objects.
/// </para>
/// <para>
/// A property of a vCard contains a piece of
/// contact information, such as an email address
/// or web site. A subproperty indicates options
/// or attributes of the property, such as the
/// type of email address or character set.
/// </para>
/// </remarks>
/// <seealso cref="vCardProperty"/>
/// <seealso cref="vCardSubproperty"/>
public class vCardSubpropertyCollection : Collection<vCardSubproperty>
{
/// <summary>
/// Adds a subproperty without a value.
/// </summary>
/// <param name="name">
/// The name of the subproperty.
/// </param>
public void Add(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
else
{
Add(new vCardSubproperty(name));
}
}
/// <summary>
/// Adds a subproperty with the specified name and value.
/// </summary>
/// <param name="name">
/// The name of the new subproperty to add.
/// </param>
/// <param name="value">
/// The value of the new subproperty to add. This can be null.
/// </param>
public void Add(string name, string value)
{
Add(new vCardSubproperty(name, value));
}
/// <summary>
/// Either adds or updates a subproperty with the specified name.
/// </summary>
/// <param name="name">
/// The name of the subproperty to add or update.
/// </param>
/// <param name="value">
/// The value of the subproperty to add or update.
/// </param>
public void AddOrUpdate(string name, string value)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
int index = IndexOf(name);
if (index == -1)
{
Add(name, value);
}
else
{
this[index].Value = value;
}
}
/// <summary>
/// Determines if the collection contains a subproperty
/// with the specified name.
/// </summary>
/// <param name="name">
/// The name of the subproperty.
/// </param>
/// <returns>
/// True if the collection contains a subproperty with the
/// specified name, or False otherwise.
/// </returns>
public bool Contains(string name)
{
foreach (vCardSubproperty sub in this)
{
if (string.Compare(name, sub.Name, StringComparison.OrdinalIgnoreCase) == 0)
return true;
}
return false;
}
/// <summary>
/// Builds a string array containing subproperty names.
/// </summary>
/// <returns>
/// A string array containing the unmodified name of
/// each subproperty in the collection.
/// </returns>
public string[] GetNames()
{
ArrayList names = new ArrayList(this.Count);
foreach (vCardSubproperty sub in this)
{
names.Add(sub.Name);
}
return (string[])names.ToArray(typeof(string));
}
/// <summary>
/// Builds a string array containing all subproperty
/// names that match one of the names in an array.
/// </summary>
/// <param name="filteredNames">
/// A list of valid subproperty names.
/// </param>
/// <returns>
/// A string array containing the names of all subproperties
/// that match an entry in the filterNames list.
/// </returns>
public string[] GetNames(string[] filteredNames)
{
if (filteredNames == null)
throw new ArgumentNullException("filteredNames");
// The vCard specification is not case-sensitive.
// Therefore the subproperty names and the filter names
// list must be compared in a case-insensitive matter.
// Whitespace will also be ignored. For better-
// performing comparisons, a processed version of
// the filtered list will be constructed.
string[] processedNames =
(string[])filteredNames.Clone();
for (int index = 0; index < processedNames.Length; index++)
{
if (!string.IsNullOrEmpty(processedNames[index]))
{
processedNames[index] =
processedNames[index].Trim().ToUpperInvariant();
}
}
// Matching names will be stored in an array list,
// and then converted to a string array for return.
ArrayList matchingNames = new ArrayList();
foreach (vCardSubproperty sub in this)
{
// Convert this subproperty name to upper case.
// The names in the processed array are already
// in upper case.
string subName =
sub.Name == null ? null : sub.Name.ToUpperInvariant();
// See if the processed subproperty name has any
// matches in the processed array.
int matchIndex =
Array.IndexOf<string>(processedNames, subName);
if (matchIndex != -1)
matchingNames.Add(processedNames[matchIndex]);
}
return (string[])matchingNames.ToArray(typeof(string));
}
/// <summary>
/// Get the value of the subproperty with
/// the specified name.
/// </summary>
/// <param name="name">
/// The name of the subproperty.
/// </param>
/// <returns>
/// The value of the subproperty or null if no
/// such subproperty exists in the collection.
/// </returns>
public string GetValue(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
// Get the collection index of the subproperty
// object that has the specified name.
int index = IndexOf(name);
if (index == -1)
{
return null;
}
else
{
return this[index].Value;
}
}
/// <summary>
/// Gets the value of the first subproperty with the
/// specified name, or the first value specified in
/// a list.
/// </summary>
/// <param name="name">
/// The expected name of the subproperty.
/// </param>
/// <param name="namelessValues">
/// A list of values that are sometimes listed as
/// subproperty names. The first matching value is
/// returned if the name parameter does not match.
/// </param>
public string GetValue(
string name,
string[] namelessValues)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
// See if the subproperty exists with the
// specified name. If so, return the value
// immediately.
int index = IndexOf(name);
if (index != -1)
{
return this[index].Value;
}
// A subproperty with the specified name does
// not exist. However, this does not mean that
// the subproperty does not exist. Some subproperty
// values can be written directly without a name.
// An example is the ENCODING property. Example:
//
// New Format: KEY;ENCODING=BASE64:....
// Old Format: KEY;BASE64:...
if ((namelessValues == null) || (namelessValues.Length == 0))
return null;
int nameIndex = IndexOfAny(namelessValues);
if (nameIndex == -1)
{
return null;
}
else
{
return this[nameIndex].Name;
}
}
/// <summary>
/// Searches for a subproperty with the specified name.
/// </summary>
/// <param name="name">
/// The name of the subproperty.
/// </param>
/// <returns>
/// The collection (zero-based) index of the first
/// subproperty that matches the specified name. The
/// function returns -1 if no match is found.
/// </returns>
public int IndexOf(string name)
{
for (int index = 0; index < this.Count; index++)
{
if (string.Compare(name, this[index].Name, StringComparison.OrdinalIgnoreCase) == 0)
{
return index;
}
}
return -1;
}
/// <summary>
/// Finds the first subproperty that has any of the
/// specified names.
/// </summary>
/// <param name="names">
/// An array of names to search.
/// </param>
/// <returns>
/// The collection index of the first subproperty with
/// the specified name, or -1 if no subproperty was found.
/// </returns>
public int IndexOfAny(string[] names)
{
if (names == null)
throw new ArgumentNullException("names");
for (int index = 0; index < this.Count; index++)
{
foreach (string name in names)
{
if (string.Compare(this[index].Name, name, StringComparison.OrdinalIgnoreCase) == 0)
{
return index;
}
}
}
return -1;
}
}
}

View File

@@ -0,0 +1,80 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Specialized;
using System.Text;
namespace Thought.vCards
{
/// <summary>
/// A collection of string values.
/// </summary>
public class vCardValueCollection : StringCollection
{
private char separator;
/// <summary>
/// Initializes an empty <see cref="vCardValueCollection"/>.
/// </summary>
public vCardValueCollection()
: base()
{
this.separator = ',';
}
/// <summary>
/// Initializes the value collection with the specified separator.
/// </summary>
/// <param name="separator">
/// The suggested character to use as a separator when
/// writing the collection as a string.
/// </param>
public vCardValueCollection(char separator)
{
this.separator = separator;
}
/// <summary>
/// Adds the contents of a StringCollection to the collection.
/// </summary>
/// <param name="values">
/// An initialized StringCollection containing zero or more values.
/// </param>
public void Add(StringCollection values)
{
if (values == null)
throw new ArgumentNullException("values");
foreach (string value in values)
Add(value);
}
/// <summary>
/// The suggested separator when writing values to a string.
/// </summary>
public char Separator
{
get
{
return this.separator;
}
set
{
this.separator = value;
}
}
}
}

View File

@@ -0,0 +1,170 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// A web site defined in a vCard.
/// </summary>
/// <seealso cref="vCardWebsiteCollection"/>
/// <seealso cref="vCardWebsiteTypes"/>
public class vCardWebsite
{
private string url;
private vCardWebsiteTypes websiteType;
/// <summary>
/// Creates a vCardWebSite object.
/// </summary>
public vCardWebsite()
{
this.url = string.Empty;
}
/// <summary>
/// Creates a new vCardWebSite object with the specified URL.
/// </summary>
/// <param name="url">
/// The URL of the web site.
/// </param>
public vCardWebsite(string url)
{
this.url = url == null ? string.Empty : url;
}
/// <summary>
/// Creates a new vCardWebSite with the
/// specified URL and classification.
/// </summary>
/// <param name="url">
/// The URL of the web site.
/// </param>
/// <param name="websiteType">
/// The classification of the web site.
/// </param>
public vCardWebsite(string url, vCardWebsiteTypes websiteType)
{
this.url = url == null ? string.Empty : url;
this.websiteType = websiteType;
}
/// <summary>
/// Indicates a personal home page.
/// </summary>
public bool IsPersonalSite
{
get
{
return (this.websiteType & vCardWebsiteTypes.Personal) ==
vCardWebsiteTypes.Personal;
}
set
{
if (value)
{
this.websiteType |= vCardWebsiteTypes.Personal;
}
else
{
this.websiteType &= ~vCardWebsiteTypes.Personal;
}
}
}
/// <summary>
/// Indicates a work-related web site.
/// </summary>
public bool IsWorkSite
{
get
{
return (this.websiteType & vCardWebsiteTypes.Work) ==
vCardWebsiteTypes.Work;
}
set
{
if (value)
{
this.websiteType |= vCardWebsiteTypes.Work;
}
else
{
this.websiteType &= ~vCardWebsiteTypes.Work;
}
}
}
/// <summary>
/// The URL of the web site.
/// </summary>
/// <remarks>
/// The format of the URL is not validated.
/// </remarks>
public string Url
{
get
{
return this.url;
}
set
{
if (value == null)
{
this.url = string.Empty;
}
else
{
this.url = value;
}
}
}
/// <summary>
/// The type of web site (e.g. home page, work, etc).
/// </summary>
public vCardWebsiteTypes WebsiteType
{
get
{
return this.websiteType;
}
set
{
this.websiteType = value;
}
}
/// <summary>
/// Returns the string representation (URL) of the web site.
/// </summary>
/// <returns>
/// The URL of the web site.
/// </returns>
public override string ToString()
{
return this.url;
}
}
}

View File

@@ -0,0 +1,61 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardWebsite"/> objects.
/// </summary>
/// <seealso cref="vCardWebsite"/>
/// <seealso cref="vCardWebsiteTypes"/>
public class vCardWebsiteCollection : Collection<vCardWebsite>
{
/// <summary>
/// Returns the first web site of the specified type. If
/// the collection does not contain a website of the specified
/// type, but does contain a default (uncategorized) website,
/// then that website will be returned.
/// </summary>
/// <param name="siteType"></param>
/// <returns></returns>
public vCardWebsite GetFirstChoice(vCardWebsiteTypes siteType)
{
vCardWebsite alternate = null;
foreach (vCardWebsite webSite in this)
{
if ((webSite.WebsiteType & siteType) == siteType)
{
return webSite;
}
else
{
if (
(alternate == null) &&
(webSite.WebsiteType == vCardWebsiteTypes.Default))
{
alternate = webSite;
}
}
}
return alternate;
}
}
}

View File

@@ -0,0 +1,45 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
namespace Thought.vCards
{
/// <summary>
/// The type or classification of a web site.
/// </summary>
/// <remarks>
/// <para>
/// The Microsoft Outlook contact editor has a field for
/// entering a web site. The default classification of
/// this web site is work-related. A personal web site
/// can be viewed or entered through the All Fields tab.
/// </para>
/// </remarks>
[Flags]
public enum vCardWebsiteTypes
{
/// <summary>
/// No web site designation.
/// </summary>
Default = 0,
/// <summary>
/// A personal home page.
/// </summary>
Personal = 1,
/// <summary>
/// A work-related web site.
/// </summary>
Work = 2
}
}

View File

@@ -0,0 +1,81 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
namespace Thought.vCards
{
/// <summary>
/// Base class for vCard generators.
/// </summary>
/// <seealso cref="vCardReader"/>
/// <seealso cref="vCardStandardWriter"/>
public abstract class vCardWriter
{
/// <summary>
/// Holds output warnings.
/// </summary>
private StringCollection warnings = new StringCollection();
/// <summary>
/// A collection of warning messages that were generated
/// during the output of a vCard.
/// </summary>
public StringCollection Warnings
{
get
{
return this.warnings;
}
}
/// <summary>
/// Writes a vCard to an I/O stream using the format
/// implemented by the class.
/// </summary>
/// <param name="card">
/// The vCard to write the I/O string.
/// </param>
/// <param name="output">
/// The text writer to use for output.
/// </param>
/// <remarks>
/// The implementor should not close or flush the stream.
/// The caller owns the stream and may not wish for the
/// stream to be closed (e.g. the caller may call the
/// function again with a different vCard).
/// </remarks>
public abstract void Write(vCard card, TextWriter output);
/// <summary>
/// Writes the vCard to the specified filename.
/// </summary>
public virtual void Write(vCard card, string filename)
{
if (card == null)
throw new ArgumentNullException("card");
using (StreamWriter output = new StreamWriter(filename))
{
Write(card, output);
}
}
}
}

186
vCardEditor/View/AboutDialog.Designer.cs generated Normal file
View File

@@ -0,0 +1,186 @@
namespace vCardEditor.View
{
partial class AboutDialog
{
/// <summary>
/// Variable nécessaire au concepteur.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Code généré par le Concepteur Windows Form
/// <summary>
/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
/// le contenu de cette méthode avec l'éditeur de code.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutDialog));
this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.logoPictureBox = new System.Windows.Forms.PictureBox();
this.labelProductName = new System.Windows.Forms.Label();
this.labelVersion = new System.Windows.Forms.Label();
this.labelCopyright = new System.Windows.Forms.Label();
this.labelCompanyName = new System.Windows.Forms.Label();
this.textBoxDescription = new System.Windows.Forms.TextBox();
this.okButton = new System.Windows.Forms.Button();
this.tableLayoutPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel
//
this.tableLayoutPanel.ColumnCount = 2;
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F));
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F));
this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0);
this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0);
this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1);
this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2);
this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 1, 3);
this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4);
this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5);
this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9);
this.tableLayoutPanel.Name = "tableLayoutPanel";
this.tableLayoutPanel.RowCount = 6;
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.Size = new System.Drawing.Size(417, 265);
this.tableLayoutPanel.TabIndex = 0;
//
// logoPictureBox
//
this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image")));
this.logoPictureBox.Location = new System.Drawing.Point(3, 3);
this.logoPictureBox.Name = "logoPictureBox";
this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6);
this.logoPictureBox.Size = new System.Drawing.Size(131, 259);
this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.logoPictureBox.TabIndex = 12;
this.logoPictureBox.TabStop = false;
//
// labelProductName
//
this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelProductName.Location = new System.Drawing.Point(143, 0);
this.labelProductName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17);
this.labelProductName.Name = "labelProductName";
this.labelProductName.Size = new System.Drawing.Size(271, 17);
this.labelProductName.TabIndex = 19;
this.labelProductName.Text = "Nom du produit";
this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// labelVersion
//
this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelVersion.Location = new System.Drawing.Point(143, 26);
this.labelVersion.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17);
this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(271, 17);
this.labelVersion.TabIndex = 0;
this.labelVersion.Text = "Version";
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// labelCopyright
//
this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelCopyright.Location = new System.Drawing.Point(143, 52);
this.labelCopyright.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17);
this.labelCopyright.Name = "labelCopyright";
this.labelCopyright.Size = new System.Drawing.Size(271, 17);
this.labelCopyright.TabIndex = 21;
this.labelCopyright.Text = "Copyright";
this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// labelCompanyName
//
this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelCompanyName.Location = new System.Drawing.Point(143, 78);
this.labelCompanyName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 17);
this.labelCompanyName.Name = "labelCompanyName";
this.labelCompanyName.Size = new System.Drawing.Size(271, 17);
this.labelCompanyName.TabIndex = 22;
this.labelCompanyName.Text = "Nom de la société";
this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// textBoxDescription
//
this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBoxDescription.Location = new System.Drawing.Point(143, 107);
this.textBoxDescription.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.textBoxDescription.Multiline = true;
this.textBoxDescription.Name = "textBoxDescription";
this.textBoxDescription.ReadOnly = true;
this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxDescription.Size = new System.Drawing.Size(271, 126);
this.textBoxDescription.TabIndex = 23;
this.textBoxDescription.TabStop = false;
this.textBoxDescription.Text = "Description";
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.okButton.Location = new System.Drawing.Point(339, 239);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 24;
this.okButton.Text = "&OK";
//
// AboutDialog
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(435, 283);
this.Controls.Add(this.tableLayoutPanel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AboutDialog";
this.Padding = new System.Windows.Forms.Padding(9);
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "AboutDialog";
this.tableLayoutPanel.ResumeLayout(false);
this.tableLayoutPanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel;
private System.Windows.Forms.PictureBox logoPictureBox;
private System.Windows.Forms.Label labelProductName;
private System.Windows.Forms.Label labelVersion;
private System.Windows.Forms.Label labelCopyright;
private System.Windows.Forms.Label labelCompanyName;
private System.Windows.Forms.TextBox textBoxDescription;
private System.Windows.Forms.Button okButton;
}
}

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace vCardEditor.View
{
partial class AboutDialog : Form
{
public AboutDialog()
{
InitializeComponent();
this.Text = String.Format("À propos de {0}", AssemblyTitle);
this.labelProductName.Text = AssemblyProduct;
this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
this.labelCopyright.Text = AssemblyCopyright;
this.labelCompanyName.Text = AssemblyCompany;
this.textBoxDescription.Text = AssemblyDescription;
}
#region Accesseurs d'attribut de l'assembly
public string AssemblyTitle
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length > 0)
{
AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
if (titleAttribute.Title != "")
{
return titleAttribute.Title;
}
}
return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
}
}
public string AssemblyVersion
{
get
{
return Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}
public string AssemblyDescription
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyDescriptionAttribute)attributes[0]).Description;
}
}
public string AssemblyProduct
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyProductAttribute)attributes[0]).Product;
}
}
public string AssemblyCopyright
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
}
}
public string AssemblyCompany
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyCompanyAttribute)attributes[0]).Company;
}
}
#endregion
}
}

View File

@@ -0,0 +1,604 @@
<?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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="logoPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VCFEditor.View
{
//public class ArgumentEventArgs : EventArgs
//{
// public object argument { get; set; }
//}
//http://stackoverflow.com/questions/3312134/does-net-have-a-built-in-eventargst
public class EventArg<T> : EventArgs
{
// Property variable
private readonly T p_EventData;
// Constructor
public EventArg(T data)
{
p_EventData = data;
}
// Property for EventArgs argument
public T Data
{
get { return p_EventData; }
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
namespace VCFEditor.View
{
public interface IMainView
{
#region All events
event EventHandler DeleteContact;
event EventHandler SaveContactsSelected;
event EventHandler<EventArg<string>> NewFileOpened;
event EventHandler<EventArg<int>> ChangeContactsSelected;
#endregion
int SelectedContactIndex { get; }
void DisplayContacts(BindingList<Contact> contacts);
void DisplayContactDetail(vCard card);
}
}

359
vCardEditor/View/MainForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,359 @@
namespace vCardEditor.View
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.tbsOpen = new System.Windows.Forms.ToolStripButton();
this.tbsSave = new System.Windows.Forms.ToolStripButton();
this.tbsDelete = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.tbsAbout = new System.Windows.Forms.ToolStripButton();
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.bsContacts = new System.Windows.Forms.BindingSource(this.components);
this.dgContacts = new System.Windows.Forms.DataGridView();
this.Column1 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.CellularPhoneValue = new System.Windows.Forms.TextBox();
this.CellularPhoneLabel = new System.Windows.Forms.Label();
this.HomePhoneValue = new System.Windows.Forms.TextBox();
this.FormattedNameValue = new System.Windows.Forms.TextBox();
this.HomePhoneLabel = new System.Windows.Forms.Label();
this.FormattedNameLabel = new System.Windows.Forms.Label();
this.menuStrip1.SuspendLayout();
this.toolStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.bsContacts)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.dgContacts)).BeginInit();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem,
this.helpToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(676, 24);
this.menuStrip1.TabIndex = 0;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openToolStripMenuItem,
this.toolStripMenuItem1,
this.quitToolStripMenuItem});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "File";
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
this.openToolStripMenuItem.Text = "&Open";
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(100, 6);
//
// quitToolStripMenuItem
//
this.quitToolStripMenuItem.Name = "quitToolStripMenuItem";
this.quitToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
this.quitToolStripMenuItem.Text = "&Quit";
//
// helpToolStripMenuItem
//
this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.aboutToolStripMenuItem});
this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.helpToolStripMenuItem.Text = "Help";
//
// aboutToolStripMenuItem
//
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(107, 22);
this.aboutToolStripMenuItem.Text = "&About";
//
// statusStrip1
//
this.statusStrip1.Location = new System.Drawing.Point(0, 431);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(676, 22);
this.statusStrip1.TabIndex = 1;
this.statusStrip1.Text = "statusStrip1";
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.tbsOpen,
this.tbsSave,
this.tbsDelete,
this.toolStripSeparator1,
this.tbsAbout});
this.toolStrip1.Location = new System.Drawing.Point(0, 24);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(676, 25);
this.toolStrip1.TabIndex = 2;
this.toolStrip1.Text = "toolStrip1";
//
// tbsOpen
//
this.tbsOpen.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsOpen.Image = ((System.Drawing.Image)(resources.GetObject("tbsOpen.Image")));
this.tbsOpen.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsOpen.Name = "tbsOpen";
this.tbsOpen.Size = new System.Drawing.Size(23, 22);
this.tbsOpen.Text = "&Open";
this.tbsOpen.Click += new System.EventHandler(this.tbsOpen_Click);
//
// tbsSave
//
this.tbsSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsSave.Image = ((System.Drawing.Image)(resources.GetObject("tbsSave.Image")));
this.tbsSave.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsSave.Name = "tbsSave";
this.tbsSave.Size = new System.Drawing.Size(23, 22);
this.tbsSave.Text = "&Save";
this.tbsSave.Click += new System.EventHandler(this.tbsSave_Click);
//
// tbsDelete
//
this.tbsDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsDelete.Image = ((System.Drawing.Image)(resources.GetObject("tbsDelete.Image")));
this.tbsDelete.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsDelete.Name = "tbsDelete";
this.tbsDelete.Size = new System.Drawing.Size(23, 22);
this.tbsDelete.Text = "Delete";
this.tbsDelete.Click += new System.EventHandler(this.tbsDelete_Click);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
//
// tbsAbout
//
this.tbsAbout.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsAbout.Image = ((System.Drawing.Image)(resources.GetObject("tbsAbout.Image")));
this.tbsAbout.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsAbout.Name = "tbsAbout";
this.tbsAbout.Size = new System.Drawing.Size(23, 22);
this.tbsAbout.Text = "&?";
this.tbsAbout.Click += new System.EventHandler(this.tbsAbout_Click);
//
// openFileDialog
//
this.openFileDialog.FileName = "openFileDialog1";
//
// dgContacts
//
this.dgContacts.AllowUserToAddRows = false;
this.dgContacts.AllowUserToDeleteRows = false;
this.dgContacts.AllowUserToResizeRows = false;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.dgContacts.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
this.dgContacts.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dgContacts.AutoGenerateColumns = false;
this.dgContacts.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.dgContacts.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.Raised;
this.dgContacts.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgContacts.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1,
this.Column2});
this.dgContacts.DataSource = this.bsContacts;
this.dgContacts.Location = new System.Drawing.Point(12, 52);
this.dgContacts.MultiSelect = false;
this.dgContacts.Name = "dgContacts";
this.dgContacts.RowHeadersVisible = false;
this.dgContacts.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgContacts.Size = new System.Drawing.Size(191, 376);
this.dgContacts.TabIndex = 3;
this.dgContacts.SelectionChanged += new System.EventHandler(this.dgContacts_SelectionChanged);
//
// Column1
//
this.Column1.DataPropertyName = "isSelected";
this.Column1.HeaderText = " ";
this.Column1.Name = "Column1";
this.Column1.Width = 50;
//
// Column2
//
this.Column2.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.Column2.DataPropertyName = "Name";
this.Column2.HeaderText = "Name";
this.Column2.Name = "Column2";
this.Column2.ReadOnly = true;
//
// groupBox1
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.CellularPhoneValue);
this.groupBox1.Controls.Add(this.CellularPhoneLabel);
this.groupBox1.Controls.Add(this.HomePhoneValue);
this.groupBox1.Controls.Add(this.FormattedNameValue);
this.groupBox1.Controls.Add(this.HomePhoneLabel);
this.groupBox1.Controls.Add(this.FormattedNameLabel);
this.groupBox1.Location = new System.Drawing.Point(209, 52);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(467, 376);
this.groupBox1.TabIndex = 4;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Contact Detail :";
//
// CellularPhoneValue
//
this.CellularPhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CellularPhoneValue.Location = new System.Drawing.Point(105, 92);
this.CellularPhoneValue.Name = "CellularPhoneValue";
this.CellularPhoneValue.Size = new System.Drawing.Size(321, 20);
this.CellularPhoneValue.TabIndex = 47;
//
// CellularPhoneLabel
//
this.CellularPhoneLabel.Location = new System.Drawing.Point(16, 92);
this.CellularPhoneLabel.Name = "CellularPhoneLabel";
this.CellularPhoneLabel.Size = new System.Drawing.Size(83, 19);
this.CellularPhoneLabel.TabIndex = 46;
this.CellularPhoneLabel.Text = "Mobile:";
this.CellularPhoneLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// HomePhoneValue
//
this.HomePhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.HomePhoneValue.Location = new System.Drawing.Point(105, 65);
this.HomePhoneValue.Name = "HomePhoneValue";
this.HomePhoneValue.Size = new System.Drawing.Size(321, 20);
this.HomePhoneValue.TabIndex = 45;
//
// FormattedNameValue
//
this.FormattedNameValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.FormattedNameValue.Location = new System.Drawing.Point(105, 38);
this.FormattedNameValue.Name = "FormattedNameValue";
this.FormattedNameValue.Size = new System.Drawing.Size(321, 20);
this.FormattedNameValue.TabIndex = 44;
//
// HomePhoneLabel
//
this.HomePhoneLabel.Location = new System.Drawing.Point(16, 65);
this.HomePhoneLabel.Name = "HomePhoneLabel";
this.HomePhoneLabel.Size = new System.Drawing.Size(83, 19);
this.HomePhoneLabel.TabIndex = 43;
this.HomePhoneLabel.Text = "Home Phone:";
this.HomePhoneLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// FormattedNameLabel
//
this.FormattedNameLabel.Location = new System.Drawing.Point(16, 38);
this.FormattedNameLabel.Name = "FormattedNameLabel";
this.FormattedNameLabel.Size = new System.Drawing.Size(83, 19);
this.FormattedNameLabel.TabIndex = 42;
this.FormattedNameLabel.Text = "Name:";
this.FormattedNameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(676, 453);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.dgContacts);
this.Controls.Add(this.toolStrip1);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.menuStrip1);
this.MainMenuStrip = this.menuStrip1;
this.Name = "MainForm";
this.Text = "MainForm";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.bsContacts)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.dgContacts)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton tbsOpen;
private System.Windows.Forms.ToolStripButton tbsSave;
private System.Windows.Forms.ToolStripButton tbsDelete;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripButton tbsAbout;
private System.Windows.Forms.OpenFileDialog openFileDialog;
private System.Windows.Forms.BindingSource bsContacts;
private System.Windows.Forms.DataGridView dgContacts;
private System.Windows.Forms.GroupBox groupBox1;
internal System.Windows.Forms.TextBox CellularPhoneValue;
internal System.Windows.Forms.Label CellularPhoneLabel;
internal System.Windows.Forms.TextBox HomePhoneValue;
internal System.Windows.Forms.TextBox FormattedNameValue;
internal System.Windows.Forms.Label HomePhoneLabel;
internal System.Windows.Forms.Label FormattedNameLabel;
private System.Windows.Forms.DataGridViewCheckBoxColumn Column1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VCFEditor.View;
using VCFEditor.Model;
using Thought.vCards;
namespace vCardEditor.View
{
public partial class MainForm : Form, IMainView
{
public event EventHandler SaveContactsSelected;
public event EventHandler DeleteContact;
public event EventHandler<EventArg<string>> NewFileOpened;
public event EventHandler<EventArg<int>> ChangeContactsSelected;
public int SelectedContactIndex
{
get
{
return dgContacts.CurrentCell.RowIndex;
}
}
public MainForm()
{
InitializeComponent();
}
private void tbsOpen_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog.ShowDialog();
if (result == DialogResult.OK)
{
string file = openFileDialog.FileName;
if (NewFileOpened != null)
NewFileOpened(sender, new EventArg<string>(file));
}
}
public void DisplayContacts(BindingList<Contact> contacts)
{
if (contacts != null)
this.bsContacts.DataSource = contacts;
}
private void tbsSave_Click(object sender, EventArgs e)
{
if (SaveContactsSelected != null)
SaveContactsSelected(sender, e);
}
private void dgContacts_SelectionChanged(object sender, EventArgs e)
{
if (ChangeContactsSelected != null)
{
int index = dgContacts.CurrentCell.RowIndex;
ChangeContactsSelected(sender, new EventArg<int>(index));
}
}
public void DisplayContactDetail(vCard card)
{
if (card == null)
throw new ArgumentException("card");
//Formatted Name
SetSummaryValue(FormattedNameValue, card.FormattedName);
//Home Phone
SetSummaryValue(HomePhoneValue, card.Phones.GetFirstChoice(vCardPhoneTypes.Home));
//Cellular Phone
SetSummaryValue(CellularPhoneValue, card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular));
}
private void SetSummaryValue(TextBox valueLabel, string value)
{
if (valueLabel == null)
throw new ArgumentNullException("valueLabel");
//Clear textbox if value is empty!
valueLabel.Text = value;
}
private void SetSummaryValue(TextBox valueLabel, vCardPhone phone)
{
valueLabel.Text = string.Empty;
if (phone != null)
SetSummaryValue(valueLabel, phone.FullNumber);
}
private void tbsDelete_Click(object sender, EventArgs e)
{
if (DeleteContact != null)
{
//commit changes...
dgContacts.EndEdit();
DeleteContact(sender, e);
}
}
private void tbsAbout_Click(object sender, EventArgs e)
{
AboutDialog dialog = new AboutDialog();
dialog.ShowDialog();
}
}
}

View File

@@ -0,0 +1,208 @@
<?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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>132, 17</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>248, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="tbsOpen.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp
olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4
4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm
YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl
5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd
HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX
0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc
hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv
S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt
5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg
g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC
</value>
</data>
<data name="tbsSave.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW
DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3
8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ
1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH
4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy
ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS
rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV
Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W
r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv
2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA
AElFTkSuQmCC
</value>
</data>
<data name="tbsDelete.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAL3SURBVDhPjZFrSJNRHMbPLLe5zXdmKyrTXEqZJWFmlJ/y
fkkplCwRsrAL5EzytlSUZM7bTDRvdDG10pIKHaaWaZmZaYpWBpJ96fJFsogtd8kRT+/Z1sXwQw/8Oec8
5/k9Ly+HLKYJVeDu8dKgC+NFQe/Mw+6pZ70mzYT4XCdEfo0Qxmr90WhJwNHpBl/M9q7DZCof6rU2GDu+
DNSjdy2EKLs3uGHiYDTYokIrZhEb8J++4ou5EQmmz9piJCwAmhsX0efthRfJQgzEOqPbXQpDWxMMzTXo
27IRVtSi58WBlz7dleLHKzuMHrLFZGwUTM3V0NQUQe3EwW2REJoLZTDVqzBbmovbQsHCgrFi/w/6fkeY
hoWYaRFAvWI5TJfLYWqoxOuEOMyWKzBfrYSuvsIMVxGSYkUtMhf0SDD/iIG+h0Gn1xJ8TD4GY1EOvlcW
wqiQY65CiW5XF9QScp5FuBbSqqcF/o0zre6Yf8DA2OmAyTQBete7wpidCkNaEow5aXi23Zt+uYaN8y3U
X+o44xfxpm4HtB2rMH+PwWAoF2M7fWGQp0KXmAB9egqmQoNwhZAGNs6xUAvFa8r0UdKSoWgHPN68Cfrc
LHyLicbckQR82x8DA3se8t5Kn7DOyvwWJyRDEBmrdMQ5uQe6JBJ8jY+HNiQcmtTTeBkcBJ1MBm1wGLSh
EWi3E6CREDcrSzihmYI9idWrUPXED60KDww6OUO7Lwa6JBkeSKWo92Lw/nACjOUqvN27l/6GmnJmOFjG
kx4odkBJnyeuTm1DrVqCdpE9ZpNlGN21CzVhS1GRx+AWj4euNavNa95qm0SWtaEFNuFZgsyTDStRPeaJ
suE1KBhgUH6Eh1tcLkrjuMhvE0HBPq2ybSXKqlxwQiVBSLrgzK+CpRE5ot5TrWIo+l2R3SNG9n0x5J1i
ZF63R0YHgyz2TH265j90RfJNMShDWVpgG57L/yy744AU9T/TvojHDs1ShrLmgjC5sCQyi/8lKk+E/xma
pQwhxPYnT5K9Ev2GYxQAAAAASUVORK5CYII=
</value>
</data>
<data name="tbsAbout.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIVSURBVDhPtVJNaxNRFM1PyE+Yn1AUXLjK0uWgDWQZwUUX
KsGFBEEcCkIwqBEpGiydsSo2kupsasdo7Yi2toh0sFZjG5JpiZo20/TpVOmH5njvm8BYahEXHji8+968
c+55l4n8F0zM+rhVWkHmdg29A/PoK1Yw8uIjOp/3xpvqBgrjLeilZbjNLXxZ34bwt6jexMVCGRndQenl
0p+NWHzPXoP3rQ3bAbQhQM0E5Np2BKprbZzrm8TIs8puE+68+r0NwwZiacCwALEBCVcAqet8JlAjk1PZ
JzsNJt6u4+FMS3ZmMV9mmFNAMhesbBZLC6oFdOsd8oVXocmdx018Ej9k1FgqiJ0zgS6qlR6BVI4iEFRN
IJlxMF/1cfTMcGiQvbskB6ZqgairJ6BCTJKYu9tlAUW1oSRsNDwfB+JXQ4PzN6s07W0ZPxDS5aSgJEFn
06Y9CaOqSauJRvMr9qmXQ4P8/RoWvU16eyBUEq5kbigwiKoOMTBQ0zbKlTq6TxihwejkZ1iOJwfEwmiC
BQ49yaW50J7Fh0xJw3IxbM3hwo2x0ICRHZzFgveTunYERK5lgo5YMxx8WPFw5Li+U8wYm66jNz+Naov+
Beqiao58N5NrPluoryJO0QeKU7sNGKPPazh9aRzGo/eYmVvEMk270fTlmzl2N3XW9xL/jv7iaxw7+wAH
E9ew//AVxE8OItv/9O/Cf0ck8gud2vKswuxNZgAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>353, 17</value>
</metadata>
<metadata name="bsContacts.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>486, 17</value>
</metadata>
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A0D2ACEB-1BCC-4E7F-9E7D-2BE25A7ABE22}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>vCardEditor</RootNamespace>
<AssemblyName>vCardEditor</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ContactRepository.cs" />
<Compile Include="IContactRepository.cs" />
<Compile Include="Model\Contact.cs" />
<Compile Include="Presenter\MainPresenter.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Thought.vCards\vCard.cs" />
<Compile Include="Thought.vCards\vCardAccessClassification.cs" />
<Compile Include="Thought.vCards\vCardCertificate.cs" />
<Compile Include="Thought.vCards\vCardCertificateCollection.cs" />
<Compile Include="Thought.vCards\vCardCollection.cs" />
<Compile Include="Thought.vCards\vCardDeliveryAddress.cs" />
<Compile Include="Thought.vCards\vCardDeliveryAddressCollection.cs" />
<Compile Include="Thought.vCards\vCardDeliveryAddressTypes.cs" />
<Compile Include="Thought.vCards\vCardDeliveryLabel.cs" />
<Compile Include="Thought.vCards\vCardDeliveryLabelCollection.cs" />
<Compile Include="Thought.vCards\vCardEmailAddress.cs" />
<Compile Include="Thought.vCards\vCardEmailAddressCollection.cs" />
<Compile Include="Thought.vCards\vCardEmailAddressType.cs" />
<Compile Include="Thought.vCards\vCardEncoding.cs" />
<Compile Include="Thought.vCards\vCardException.cs" />
<Compile Include="Thought.vCards\vCardFormat.cs" />
<Compile Include="Thought.vCards\vCardGender.cs" />
<Compile Include="Thought.vCards\vCardNote.cs" />
<Compile Include="Thought.vCards\vCardNoteCollection.cs" />
<Compile Include="Thought.vCards\vCardPhone.cs" />
<Compile Include="Thought.vCards\vCardPhoneCollection.cs" />
<Compile Include="Thought.vCards\vCardPhoneTypes.cs" />
<Compile Include="Thought.vCards\vCardPhoto.cs" />
<Compile Include="Thought.vCards\vCardPhotoCollection.cs" />
<Compile Include="Thought.vCards\vCardProperty.cs" />
<Compile Include="Thought.vCards\vCardPropertyCollection.cs" />
<Compile Include="Thought.vCards\vCardReader.cs" />
<Compile Include="Thought.vCards\vCardSource.cs" />
<Compile Include="Thought.vCards\vCardSourceCollection.cs" />
<Compile Include="Thought.vCards\vCardStandardReader.cs" />
<Compile Include="Thought.vCards\vCardStandardWriter.cs" />
<Compile Include="Thought.vCards\vCardStandardWriterOptions.cs" />
<Compile Include="Thought.vCards\vCardSubproperty.cs" />
<Compile Include="Thought.vCards\vCardSubpropertyCollection.cs" />
<Compile Include="Thought.vCards\vCardValueCollection.cs" />
<Compile Include="Thought.vCards\vCardWebsite.cs" />
<Compile Include="Thought.vCards\vCardWebsiteCollection.cs" />
<Compile Include="Thought.vCards\vCardWebsiteTypes.cs" />
<Compile Include="Thought.vCards\vCardWriter.cs" />
<Compile Include="Thought.vCards\WarningMessages.Designer.cs" />
<Compile Include="View\AboutDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\AboutDialog.Designer.cs">
<DependentUpon>AboutDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\EventArgs.cs" />
<Compile Include="View\IMainView.cs" />
<Compile Include="View\MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<EmbeddedResource Include="Thought.vCards\WarningMessages.resx" />
<EmbeddedResource Include="View\AboutDialog.resx">
<DependentUpon>AboutDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,31 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace vCardEditor_Test
{
/// <summary>
///
/// </summary>
[TestClass]
public class MainPresenterTest
{
public MainPresenterTest()
{
//
// TODO:
//
}
[TestMethod]
public void TestMethod1()
{
//
// TODO:
//
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Les informations générales relatives à un assembly dépendent de
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
// associées à un assembly.
[assembly: AssemblyTitle("vCardEditor_Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("vCardEditor_Test")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
// aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
// COM, affectez la valeur true à l'attribut ComVisible sur ce type.
[assembly: ComVisible(false)]
// Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
[assembly: Guid("d36513f5-c8e3-47bb-a474-830447685b12")]
// Les informations de version pour un assembly se composent des quatre valeurs suivantes :
//
// Version principale
// Version secondaire
// Numéro de build
// Révision
//
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de révision et de build par défaut
// en utilisant '*', comme indiqué ci-dessous :
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{76D5F727-2E1A-46B5-BD35-F8F9B5881FEE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>vCardEditor_Test</RootNamespace>
<AssemblyName>vCardEditor_Test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
<Visible>False</Visible>
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>