Index: extensions/PiwigoLib/Piwigo.sln
===================================================================
--- extensions/PiwigoLib/Piwigo.sln	(revision 3816)
+++ extensions/PiwigoLib/Piwigo.sln	(revision 3816)
@@ -0,0 +1,26 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PiwigoLib", "PiwigoLib\PiwigoLib.csproj", "{64C068C5-DBFE-4712-9081-B9100698F35C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPiwigoLib", "TestPiwigoLib\TestPiwigoLib.csproj", "{9B390DE8-884A-433D-828A-C7B969F19924}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{64C068C5-DBFE-4712-9081-B9100698F35C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{64C068C5-DBFE-4712-9081-B9100698F35C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{64C068C5-DBFE-4712-9081-B9100698F35C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{64C068C5-DBFE-4712-9081-B9100698F35C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9B390DE8-884A-433D-828A-C7B969F19924}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9B390DE8-884A-433D-828A-C7B969F19924}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9B390DE8-884A-433D-828A-C7B969F19924}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9B390DE8-884A-433D-828A-C7B969F19924}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: extensions/PiwigoLib/PiwigoLib/DTO/Helper/PwgEnumHelper.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/DTO/Helper/PwgEnumHelper.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/DTO/Helper/PwgEnumHelper.cs	(revision 3816)
@@ -0,0 +1,42 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Reflection;
+using System.ComponentModel;
+using System.Xml.Serialization;
+
+namespace Com.Piwigo.Lib.DTO.Helper
+{
+    public static class PwgEnumHelper<T>
+    {
+        public static string stringValueOf(T value)
+        {
+            FieldInfo fi = value.GetType().GetField(value.ToString());
+            XmlEnumAttribute[] attributes = (XmlEnumAttribute[])fi.GetCustomAttributes(typeof(XmlEnumAttribute), false);
+            if (attributes.Length > 0)
+            {
+                return attributes[0].Name;
+            }
+            else
+            {
+                return value.ToString();
+            }
+        }
+
+        public static T enumValueOf(string value)
+        {
+            Type enumType = typeof(T);
+            Array values = Enum.GetValues(enumType);
+            foreach (T enumValue in values)
+            {
+                if (stringValueOf(enumValue).Equals(value))
+                {
+                    return enumValue;
+                }
+            }
+
+            throw new ArgumentException("The string is not a description or value of the specified enum.");
+        }
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/DTO/PwgSession.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/DTO/PwgSession.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/DTO/PwgSession.cs	(revision 3816)
@@ -0,0 +1,22 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+
+namespace Com.Piwigo.Lib.DTO
+{
+
+    public class PwgSession
+    {
+        public Boolean IsConnected {
+            get { return this.Status != PwgSessionStatusEnum.Guest; }
+        }
+ 
+        public String UserName              { get; set; }
+        public PwgSessionStatusEnum Status  { get; set; }
+        public String Template              { get; set; }
+        public String Theme                 { get; set; }
+        public String Language              { get; set; }
+        public String CharSet               { get; set; }    
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/DTO/PwgSessionStatusEnum.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/DTO/PwgSessionStatusEnum.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/DTO/PwgSessionStatusEnum.cs	(revision 3816)
@@ -0,0 +1,23 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace Com.Piwigo.Lib.DTO
+{
+
+    [Serializable()]
+    [XmlRoot(ElementName = "PwgSessionStatusEnum")]
+    public enum PwgSessionStatusEnum : int
+    {
+        [XmlEnum("unknow")]
+        Unknow = 0,
+        [XmlEnum("guest")]
+        Guest = 1,
+        [XmlEnum("normal")]
+        Nomal = 2,
+        [XmlEnum("webmaster")]
+        WebMaster = 3
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/DTO/PwgTag.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/DTO/PwgTag.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/DTO/PwgTag.cs	(revision 3816)
@@ -0,0 +1,17 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+
+namespace Com.Piwigo.Lib.DTO
+{
+
+    public class PwgTag
+    {
+        public Int16  Id      { get; set; }
+        public String Name    { get; set; }
+        public String UrlName { get; set; }
+        public Int64  Counter { get; set; }
+        public Uri    UrlTag  { get; set; }
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/PiwigoLib.csproj
===================================================================
--- extensions/PiwigoLib/PiwigoLib/PiwigoLib.csproj	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/PiwigoLib.csproj	(revision 3816)
@@ -0,0 +1,75 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{64C068C5-DBFE-4712-9081-B9100698F35C}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Com.Piwigo.Lib</RootNamespace>
+    <AssemblyName>PiwigoLib</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </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>
+    <Reference Include="System.Web" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DTO\Helper\PwgEnumHelper.cs" />
+    <Compile Include="DTO\PwgSessionStatusEnum.cs" />
+    <Compile Include="DTO\PwgTag.cs" />
+    <Compile Include="DTO\PwgSession.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Proxy\PwgTagsProxy.cs" />
+    <Compile Include="Proxy\Response\PwgTagsProxyResponse.cs" />
+    <Compile Include="Proxy\Response\PwgBaseProxyReponse.cs" />
+    <Compile Include="Proxy\Response\PwgBaseProxyReponseRetourEnum.cs" />
+    <Compile Include="Proxy\Response\PwgSessionProxyResponse.cs" />
+    <Compile Include="Proxy\PwgConfigProxy.cs" />
+    <Compile Include="Proxy\PwgGenericProxy.cs" />
+    <Compile Include="Proxy\PwgProxyException.cs" />
+    <Compile Include="Proxy\PwgSessionProxy.cs" />
+    <Compile Include="Service\PwgTagsService.cs" />
+    <Compile Include="Service\PwgServiceException.cs" />
+    <Compile Include="Service\PwgSessionService.cs" />
+  </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>
Index: extensions/PiwigoLib/PiwigoLib/Properties/AssemblyInfo.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Properties/AssemblyInfo.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Properties/AssemblyInfo.cs	(revision 3816)
@@ -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("PiwigoLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PiwigoLib")]
+[assembly: AssemblyCopyright("Copyright ©  2009")]
+[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("502c1632-dabd-40d2-ac0f-61cc18c4ca42")]
+
+// 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")]
Index: extensions/PiwigoLib/PiwigoLib/Proxy/PwgConfigProxy.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/PwgConfigProxy.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/PwgConfigProxy.cs	(revision 3816)
@@ -0,0 +1,20 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Net;
+
+namespace Com.Piwigo.Lib.Proxy
+{
+    public static class PwgConfigProxy
+    {
+        public static String PwgUserAgent = "PiwigoLib.GenericProxy";
+        public static Boolean PwgKeepAlive = false;
+        public static Int16 PwgTimeOutInSecond = 15;
+
+        public static UriBuilder PwgServeurUriBuilder = new UriBuilder(); // store uri piece of the server
+
+        public static CookieContainer cookieContainer = new CookieContainer(); // store cookie as session once
+
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Proxy/PwgGenericProxy.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/PwgGenericProxy.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/PwgGenericProxy.cs	(revision 3816)
@@ -0,0 +1,188 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Net;
+using System.IO;
+
+using System.Web;
+using System.Xml.Serialization;
+using System.Xml;
+
+namespace Com.Piwigo.Lib.Proxy
+{
+
+    static class PwgGenericProxy<T>
+    {
+        
+        public static T Get(Uri address, String methodName, String methodParameter)
+        {
+            T ReturnValue = default(T);
+            HttpWebRequest Request;
+            HttpWebResponse Response = null;
+            StreamReader Reader;
+
+            if (address == null) { throw new PwgProxyException("The get address is null."); }
+
+            try
+            {
+                UriBuilder completeUri = new UriBuilder(address);
+                if (methodParameter == null)
+                {
+                    completeUri.Query = String.Format("method={0}", methodName);
+                }
+                else
+                {
+                    completeUri.Query = String.Format("method={0}&{1}", methodName, methodParameter);
+                }
+                // Create and initialize the web request  
+                Request = WebRequest.Create(completeUri.Uri) as HttpWebRequest;
+                Request.UserAgent = PwgConfigProxy.PwgUserAgent;
+                Request.KeepAlive = PwgConfigProxy.PwgKeepAlive;
+                Request.Timeout = PwgConfigProxy.PwgTimeOutInSecond * 1000;
+                Request.CookieContainer = PwgConfigProxy.cookieContainer; // get session cookie
+
+                // Get response  
+                Response = Request.GetResponse() as HttpWebResponse;
+
+                if (Request.HaveResponse == true && Response != null)
+                {
+                    // Get the response stream  
+                    Reader = new StreamReader(Response.GetResponseStream());
+
+                    ReturnValue = DeserializeObject(Reader);
+                }
+            }
+            catch (WebException wex)
+            {
+                // This exception will be raised if the server didn't return 200 - OK  
+                // Try to retrieve more information about the network error  
+                if (wex.Response != null)
+                {
+                    using (HttpWebResponse errorResponse = (HttpWebResponse)wex.Response)
+                    {
+                        throw new PwgProxyException(
+                            String.Format(
+                                "The server returned '{0}' with the status code {1} ({2:d}).",
+                                errorResponse.StatusDescription, errorResponse.StatusCode,
+                                errorResponse.StatusCode),
+                                wex);
+                    }
+                }
+            }
+            finally
+            {
+                if (Response != null) { Response.Close(); }
+            }
+            return ReturnValue;
+        }
+
+        public static T Post(Uri address, String data)
+        {
+            T ReturnValue = default(T);
+
+            HttpWebRequest Request;
+            HttpWebResponse Response = null;
+
+            if (address == null) { throw new PwgProxyException("The get address is null."); }
+
+            try
+            {
+                // Create the web request  
+                Request = WebRequest.Create(address) as HttpWebRequest;
+                Request.UserAgent = PwgConfigProxy.PwgUserAgent;
+                Request.KeepAlive = PwgConfigProxy.PwgKeepAlive;
+                Request.Timeout = PwgConfigProxy.PwgTimeOutInSecond * 1000;
+                Request.CookieContainer = PwgConfigProxy.cookieContainer; // get session cookie
+
+                // Set type to POST  
+                Request.Method = "POST";
+                Request.ContentType = "application/x-www-form-urlencoded";
+
+                // Create a byte array of the data we want to send  
+                byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
+
+                // Set the content length in the request headers  
+                Request.ContentLength = byteData.Length;
+
+                // Write data  
+                using (Stream PostStream = Request.GetRequestStream())
+                {
+                    PostStream.Write(byteData, 0, byteData.Length);
+                }
+
+                // Get response  
+                using (Response = Request.GetResponse() as HttpWebResponse)
+                {
+                    // Get the response stream  
+                    StreamReader reader = new StreamReader(Response.GetResponseStream());
+
+                    ReturnValue = DeserializeObject(reader);
+                }
+            }
+            catch (WebException wex)
+            {
+                // This exception will be raised if the server didn't return 200 - OK  
+                // Try to retrieve more information about the network error  
+                if (wex.Response != null)
+                {
+                    using (HttpWebResponse ErrorResponse = (HttpWebResponse)wex.Response)
+                    {
+                        throw new PwgProxyException(
+                            String.Format(
+                                "The server returned '{0}' with the status code {1} ({2:d}).",
+                                ErrorResponse.StatusDescription, ErrorResponse.StatusCode,
+                                ErrorResponse.StatusCode),
+                            wex);
+                    }
+                }
+            }
+            finally
+            {
+                if (Response != null) { Response.Close(); }
+            }
+            return ReturnValue;
+        }
+
+        public static T DeserializeObject(StreamReader xmlData)
+        {
+            T ReturnValue = default(T);
+
+            try
+            {
+                //Console.WriteLine(xmlData.ReadToEnd());
+
+                System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
+                ReturnValue = (T)xsSerializer.Deserialize(xmlData);
+            }
+            catch (Exception ex)
+            {
+                throw new PwgProxyException(
+                            String.Format(
+                                "The value {0} can't be deserialized in {1}, the error is {2} .",
+                                xmlData, typeof(T).Name, ex.Message),
+                            ex);
+            }
+
+            return ReturnValue;
+        }
+
+        public static void SerializeToXML(String fileName,T obj  )
+        {
+            try
+            {
+                XmlSerializer serializer = new XmlSerializer(typeof(T));
+                TextWriter textWriter = new StreamWriter(fileName);
+                serializer.Serialize(textWriter, obj);
+                textWriter.Close();
+            }
+            catch (Exception ex)
+            {
+                throw new PwgProxyException(
+                            String.Format(
+                                "The value {0} can't be serialized in {1}, the error is {2} .",
+                                obj, fileName, ex.Message),
+                            ex);
+            }
+        }
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Proxy/PwgProxyException.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/PwgProxyException.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/PwgProxyException.cs	(revision 3816)
@@ -0,0 +1,26 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Com.Piwigo.Lib.Proxy
+{
+    public sealed class PwgProxyException : ApplicationException 
+    {
+        private static String Defaut_Message = "A PwgProxyException occurs...";
+        public PwgProxyException() 
+            : base(Defaut_Message)
+        {
+        }
+
+        public PwgProxyException(String message)
+            : base(Defaut_Message + " " + message)
+        {
+        }
+
+        public PwgProxyException(String message, Exception innerEx)
+            : base(Defaut_Message + " " + message, innerEx)
+        {
+        }
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Proxy/PwgSessionProxy.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/PwgSessionProxy.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/PwgSessionProxy.cs	(revision 3816)
@@ -0,0 +1,75 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Com.Piwigo.Lib.DTO;
+using System.Web;
+using Com.Piwigo.Lib.Proxy.Response;
+
+namespace Com.Piwigo.Lib.Proxy
+{
+    static class PwgSessionProxy
+    {
+        static public PwgSessionProxyResponse pwg_session_getStatus()
+        {
+            PwgSessionProxyResponse response = null;
+            try
+            {            
+            response = PwgGenericProxy<PwgSessionProxyResponse>.Get(
+                                PwgConfigProxy.PwgServeurUriBuilder.Uri, 
+                                "pwg.session.getStatus", null);
+            }
+            catch (Exception ex)
+            {
+                throw new PwgProxyException("pwg_session_getStatus", ex);
+            }
+            return response;
+
+        }
+
+        static public PwgSessionProxyResponse pwg_session_login(string UserName, string Password)
+        {
+            PwgSessionProxyResponse response = null;
+            try
+            {
+                StringBuilder data = new StringBuilder();
+                data.Append("method=pwg.session.login");
+                data.Append("&username=" + HttpUtility.UrlEncode(UserName));
+                data.Append("&password=" + HttpUtility.UrlEncode(Password));
+
+
+                response = PwgGenericProxy<PwgSessionProxyResponse>.Post(
+                    PwgConfigProxy.PwgServeurUriBuilder.Uri, 
+                    data.ToString());
+            }
+            catch (Exception ex)
+            {
+                throw new PwgProxyException("pwg_session_login",ex);
+            }
+
+            return response;
+        }
+
+        static public PwgSessionProxyResponse pwg_session_logout()
+        {
+            PwgSessionProxyResponse response = null;
+            try
+            {
+                StringBuilder data = new StringBuilder();
+                data.Append("method=pwg.session.logout");
+
+                response = PwgGenericProxy<PwgSessionProxyResponse>.Post(
+                    PwgConfigProxy.PwgServeurUriBuilder.Uri,
+                    data.ToString());
+            }
+            catch (Exception ex)
+            {
+                throw new PwgProxyException("pwg_session_logout", ex);
+            }
+            return response;
+        }
+
+    }
+
+}
+
Index: extensions/PiwigoLib/PiwigoLib/Proxy/PwgTagsProxy.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/PwgTagsProxy.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/PwgTagsProxy.cs	(revision 3816)
@@ -0,0 +1,35 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Com.Piwigo.Lib.DTO;
+using System.Web;
+using Com.Piwigo.Lib.Proxy.Response;
+
+namespace Com.Piwigo.Lib.Proxy
+{
+    static class PwgTagsProxy
+    {
+        static public PwgTagsProxyResponse pwg_tags_getList(Boolean sortedByCounter)
+        {
+            PwgTagsProxyResponse response = null;
+            try
+            {
+                StringBuilder data = new StringBuilder();
+                data.Append("sort_by_counter=" + HttpUtility.UrlEncode(sortedByCounter.ToString().ToLower()));
+
+                response = PwgGenericProxy<PwgTagsProxyResponse>.Get(
+                                PwgConfigProxy.PwgServeurUriBuilder.Uri,
+                                "pwg.tags.getList", data.ToString());
+            }
+            catch (Exception ex)
+            {
+                throw new PwgProxyException("pwg_tags_getList", ex);
+            }
+            return response;
+
+        }
+    }
+
+}
+
Index: extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgBaseProxyReponse.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgBaseProxyReponse.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgBaseProxyReponse.cs	(revision 3816)
@@ -0,0 +1,33 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace Com.Piwigo.Lib.Proxy.Response
+{
+
+    [Serializable()]
+    [XmlRoot(ElementName = "err")]
+    public class PwgBaseProxyReponseError
+    {
+        [XmlAttribute(AttributeName = "code")]
+        public Int32 Code { get; set; }
+
+        [XmlAttribute(AttributeName = "msg")]
+        public String Message { get; set; }
+    }
+
+
+    [Serializable()]
+    [XmlRoot(ElementName = "rsp")]
+    public abstract class PwgBaseProxyReponse
+    {
+        [XmlAttribute(AttributeName="stat")]
+        public PwgBaseProxyReponseRetourEnum Retour { get; set; }
+
+        [XmlElement( ElementName="err")]
+        public PwgBaseProxyReponseError Erreur { get; set; }
+
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgBaseProxyReponseRetourEnum.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgBaseProxyReponseRetourEnum.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgBaseProxyReponseRetourEnum.cs	(revision 3816)
@@ -0,0 +1,20 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace Com.Piwigo.Lib.Proxy.Response
+{
+    [Serializable()]
+    [XmlRoot(ElementName = "PwgBaseProxyReponseRetourEnum")]
+    public enum PwgBaseProxyReponseRetourEnum : int
+    {
+        [XmlEnum("unknow")]
+        Unknow = 0,
+        [XmlEnum("ok")]
+        Ok = 1,
+        [XmlEnum("fail")]
+        Fail = 2
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgSessionProxyResponse.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgSessionProxyResponse.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgSessionProxyResponse.cs	(revision 3816)
@@ -0,0 +1,33 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+using Com.Piwigo.Lib.DTO;
+
+namespace Com.Piwigo.Lib.Proxy.Response
+{
+    [Serializable()]
+    [XmlRoot(ElementName = "tag")]
+    public class PwgTagProxyResponse
+    {
+        [XmlElement(ElementName = "id")]
+        public Int16 Id { get; set; }
+        [XmlElement(ElementName = "name")]
+        public String Name { get; set; }
+        [XmlElement(ElementName = "url_name")]
+        public String UrlName { get; set; }
+        [XmlElement(ElementName = "counter")]
+        public Int64 Counter { get; set; }
+        [XmlElement(ElementName = "url")]
+        public String UrlTag { get; set; }
+    }
+
+    [Serializable()]
+    [XmlRoot(ElementName = "rsp")]
+    public class PwgTagsProxyResponse : PwgBaseProxyReponse
+    {
+        [XmlElement(ElementName = "tags")]
+        public List<PwgTagProxyResponse> Tags { get; set; }
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgTagsProxyResponse.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgTagsProxyResponse.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Proxy/Response/PwgTagsProxyResponse.cs	(revision 3816)
@@ -0,0 +1,28 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+using Com.Piwigo.Lib.DTO;
+
+namespace Com.Piwigo.Lib.Proxy.Response
+{
+    [Serializable()]
+    [XmlRoot(ElementName = "rsp")]
+
+    public class PwgSessionProxyResponse : PwgBaseProxyReponse
+    {
+        [XmlElement(ElementName = "username")]
+        public String UserName { get; set; }
+        [XmlElement(ElementName = "status")]
+        public string Status { get; set; }
+        [XmlElement(ElementName = "template")]
+        public String Template { get; set; }
+        [XmlElement(ElementName = "theme")]
+        public String Theme { get; set; }
+        [XmlElement(ElementName = "language")]
+        public String Language { get; set; }
+        [XmlElement(ElementName = "charset")]
+        public String CharSet { get; set; }    
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Service/PwgServiceException.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Service/PwgServiceException.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Service/PwgServiceException.cs	(revision 3816)
@@ -0,0 +1,50 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Com.Piwigo.Lib.Proxy
+{
+    public sealed class  PwgServiceException : ApplicationException 
+    {
+        public Int32 NumeroErr { get; private set; }
+        public String MessageErr { get; private set; }
+
+        private static String Defaut_Message = "A PwgServiceException occurs...";
+        public PwgServiceException() 
+            : base(Defaut_Message)
+        {
+            NumeroErr = 0;
+            MessageErr = String.Empty;
+        }
+
+        public PwgServiceException(String message)
+            : base(Defaut_Message + " " + message)
+        {
+            NumeroErr = 0;
+            MessageErr = String.Empty;
+        }
+
+        public PwgServiceException(String message, Exception innerEx)
+            : base(Defaut_Message + " " + message, innerEx)
+        {
+            NumeroErr = 0;
+            MessageErr = String.Empty;
+        }
+
+        public PwgServiceException(String message, Int32 NumErr, String MsgErr)
+            : base(Defaut_Message + " " + message)
+        {
+            NumeroErr = NumErr;
+            MessageErr = MsgErr;
+        }
+
+        public PwgServiceException(String message, Int32 NumErr, String MsgErr, Exception innerEx)
+            : base(Defaut_Message + " " + message, innerEx)
+        {
+            NumeroErr = NumErr;
+            MessageErr = MsgErr;
+        }
+
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Service/PwgSessionService.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Service/PwgSessionService.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Service/PwgSessionService.cs	(revision 3816)
@@ -0,0 +1,142 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Com.Piwigo.Lib.DTO;
+using Com.Piwigo.Lib.Proxy;
+using Com.Piwigo.Lib.Proxy.Response;
+using Com.Piwigo.Lib.DTO.Helper;
+
+namespace Com.Piwigo.Lib.Service
+{
+  
+    static public class PwgSessionService
+    {
+        static private PwgSession PwgSession = null;
+
+        /// <summary>
+        /// Return informations about user logged
+        /// </summary>
+        /// <returns></returns>
+        static public PwgSession GetPwgSession()
+        {
+            if (PwgSession == null)
+            {
+                try
+                {
+                    PwgSessionProxyResponse response = PwgSessionProxy.pwg_session_getStatus();
+
+                    if (response.Retour != PwgBaseProxyReponseRetourEnum.Ok)
+                    {
+                        if (response.Erreur != null)
+                        {
+                            throw new PwgServiceException("GetPwgSession, the server has return the error.", 
+                                response.Erreur.Code,
+                                response.Erreur.Message);
+                        }
+                        else
+                        {
+                            throw new PwgServiceException("GetPwgSession : a error occurs during server process.");
+                        }
+                    }
+                    else
+                    {
+                        ConvertProxyResponseToDTO(response, ref PwgSession);
+                    }
+                } catch (PwgProxyException ex)
+                {
+                    throw new PwgServiceException("GetPwgSession : a error is raised by proxy.", ex);
+                }
+
+            }
+
+            return PwgSession;
+        }
+        /// <summary>
+        /// Log to the gallery using a account
+        /// </summary>
+        /// <param name="UserName"></param>
+        /// <param name="Password"></param>
+        /// <returns></returns>
+        static public PwgSession Login(String UserName, String Password)
+        {
+            PwgSession = null;
+            try
+            {
+                PwgSessionProxyResponse response = PwgSessionProxy.pwg_session_login(UserName, Password);
+
+                if (response.Retour != PwgBaseProxyReponseRetourEnum.Ok )
+                {
+                    if (response.Erreur != null)
+                    {
+                        throw new PwgServiceException("Login, the server has return the error.", 
+                            response.Erreur.Code, 
+                            response.Erreur.Message);
+                    }
+                    else
+                    {
+                        throw new PwgServiceException("Login : a error occurs during server process.");
+                    }
+                }
+            }
+            catch (PwgProxyException ex)
+            {
+                throw new PwgServiceException("Login : a error is raised by proxy.", ex);
+            }
+
+            return GetPwgSession();
+        }
+
+        static public PwgSession Logout()
+        {
+            PwgSession = null;
+            try
+            {
+                PwgSessionProxyResponse response = PwgSessionProxy.pwg_session_logout();
+
+                if (response.Retour != PwgBaseProxyReponseRetourEnum.Ok )
+                {
+                    if (response.Erreur != null)
+                    {
+                        throw new PwgServiceException("Logout, the server has return the error.",
+                            response.Erreur.Code, 
+                            response.Erreur.Message);
+                    }
+                    else
+                    {
+                        throw new PwgServiceException("Logout : a error occurs during server process.");
+                    }
+                }
+            }
+            catch (PwgProxyException ex)
+            {
+                throw new PwgServiceException("Logout : a error is raised by proxy.", ex);
+            }
+
+            return GetPwgSession();
+        }
+        /// <summary>
+        /// private: convert response to dto object
+        /// </summary>
+        /// <param name="response"></param>
+        /// <param name="session"></param>
+        static private void ConvertProxyResponseToDTO(PwgSessionProxyResponse response, ref PwgSession session)
+        {
+            if (session == null)
+            {
+                session = new PwgSession();
+            }
+
+            if (response != null)
+            {
+                session.CharSet = response.CharSet;
+                session.Language = response.Language;
+                session.Status = PwgEnumHelper<PwgSessionStatusEnum>.enumValueOf(response.Status);
+                session.Template = response.Template;
+                session.Theme = response.Theme;
+                session.UserName = response.UserName;
+            }
+
+        }
+    }
+}
Index: extensions/PiwigoLib/PiwigoLib/Service/PwgTagsService.cs
===================================================================
--- extensions/PiwigoLib/PiwigoLib/Service/PwgTagsService.cs	(revision 3816)
+++ extensions/PiwigoLib/PiwigoLib/Service/PwgTagsService.cs	(revision 3816)
@@ -0,0 +1,61 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Com.Piwigo.Lib.DTO;
+using Com.Piwigo.Lib.Proxy;
+using Com.Piwigo.Lib.Proxy.Response;
+using Com.Piwigo.Lib.DTO.Helper;
+
+namespace Com.Piwigo.Lib.Service
+{
+  
+    static public class PwgTagsService
+    {
+
+        static public List<PwgTag> GetListOfPwgTag(Boolean sortedByCounter)
+        {
+            List<PwgTag> returnValue = new List<PwgTag>();
+
+            try
+            {
+                PwgTagsProxyResponse response = PwgTagsProxy.pwg_tags_getList(sortedByCounter);
+
+                if (response.Retour != PwgBaseProxyReponseRetourEnum.Ok)
+                {
+                    if (response.Erreur != null)
+                    {
+                        throw new PwgServiceException("GetListOfPwgTag, the server has return the error.",
+                            response.Erreur.Code,
+                            response.Erreur.Message);
+                    }
+                    else
+                    {
+                        throw new PwgServiceException("GetListOfPwgTag : a error occurs during server process.");
+                    }
+                }
+                else
+                {
+                    returnValue = ConvertProxyResponseToDTO(response);
+                }
+            }
+            catch (PwgProxyException ex)
+            {
+                throw new PwgServiceException("GetListOfPwgTag : a error is raised by proxy.", ex);
+            }
+            return returnValue;
+        }
+
+        /// <summary>
+        /// private: convert response to dto object
+        /// </summary>
+        /// <param name="response"></param>
+        /// <param name="session"></param>
+        static private List<PwgTag> ConvertProxyResponseToDTO(PwgTagsProxyResponse response)
+        {
+            List<PwgTag> returnValue = new List<PwgTag>();
+
+            return returnValue;
+        }
+    }
+}
Index: extensions/PiwigoLib/TestPiwigoLib/Form1.Designer.cs
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Form1.Designer.cs	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Form1.Designer.cs	(revision 3816)
@@ -0,0 +1,48 @@
+﻿namespace TestPiwigoLib
+{
+    partial class Form1
+    {
+        /// <summary>
+        /// Variable nécessaire au concepteur.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Nettoyage des ressources utilisées.
+        /// </summary>
+        /// <param name="disposing">true si les ressources managées doivent être supprimées ; sinon, false.</param>
+        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()
+        {
+            this.SuspendLayout();
+            // 
+            // Form1
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(292, 266);
+            this.Name = "Form1";
+            this.Text = "Form1";
+            this.Load += new System.EventHandler(this.Form1_Load);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+    }
+}
+
Index: extensions/PiwigoLib/TestPiwigoLib/Form1.cs
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Form1.cs	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Form1.cs	(revision 3816)
@@ -0,0 +1,59 @@
+﻿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 Com.Piwigo.Lib.Proxy;
+using Com.Piwigo.Lib.Service;
+using Com.Piwigo.Lib.DTO;
+
+
+namespace TestPiwigoLib
+{
+    public partial class Form1 : Form
+    {
+        public Form1()
+        {
+            InitializeComponent();
+        }
+
+        private void Form1_Load(object sender, EventArgs e)
+        {
+            PwgConfigProxy.PwgUserAgent = "TestPiwigoLib";
+            PwgConfigProxy.PwgServeurUriBuilder.Host = "bayral.free.fr";
+            PwgConfigProxy.PwgServeurUriBuilder.Path = "phpwebgallery/ws.php";
+            PwgConfigProxy.PwgServeurUriBuilder.Scheme = "http://";
+
+            Console.WriteLine(PwgConfigProxy.PwgServeurUriBuilder.Uri.AbsoluteUri);
+
+            try
+            {
+                PwgSession sess = null;
+                sess = PwgSessionService.GetPwgSession();
+                Console.WriteLine("user : " + sess.UserName + " "+ sess.Status);
+
+                sess = PwgSessionService.Login("invite", "ayral");
+                Console.WriteLine("user : " + sess.UserName + " " + sess.Status);
+
+                List<PwgTag> lstTag = PwgTagsService.GetListOfPwgTag(false);
+
+                sess = PwgSessionService.Logout();
+                Console.WriteLine("user : " + sess.UserName + " " + sess.Status);
+
+                sess = PwgSessionService.Login("bayral", "jamb0bnt");
+                Console.WriteLine("user : " + sess.UserName + " " + sess.Status);
+            }
+            catch (PwgServiceException ex)
+            {
+                Console.WriteLine("Erreur " + ex.NumeroErr + " " + ex.MessageErr);
+            }
+
+            
+
+        }
+    }
+}
Index: extensions/PiwigoLib/TestPiwigoLib/Form1.resx
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Form1.resx	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Form1.resx	(revision 3816)
@@ -0,0 +1,120 @@
+<?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>
+</root>
Index: extensions/PiwigoLib/TestPiwigoLib/Program.cs
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Program.cs	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Program.cs	(revision 3816)
@@ -0,0 +1,21 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace TestPiwigoLib
+{
+    static class Program
+    {
+        /// <summary>
+        /// Point d'entrée principal de l'application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new Form1());
+        }
+    }
+}
Index: extensions/PiwigoLib/TestPiwigoLib/Properties/AssemblyInfo.cs
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Properties/AssemblyInfo.cs	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Properties/AssemblyInfo.cs	(revision 3816)
@@ -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("TestPiwigoLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TestPiwigoLib")]
+[assembly: AssemblyCopyright("Copyright ©  2009")]
+[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("858586e2-b217-49eb-bee3-7a70e25995b5")]
+
+// 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")]
Index: extensions/PiwigoLib/TestPiwigoLib/Properties/Resources.Designer.cs
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Properties/Resources.Designer.cs	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Properties/Resources.Designer.cs	(revision 3816)
@@ -0,0 +1,71 @@
+﻿//------------------------------------------------------------------------------
+// <auto-generated>
+//     Ce code a été généré par un outil.
+//     Version du runtime :2.0.50727.3082
+//
+//     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 TestPiwigoLib.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", "2.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("TestPiwigoLib.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;
+            }
+        }
+    }
+}
Index: extensions/PiwigoLib/TestPiwigoLib/Properties/Resources.resx
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Properties/Resources.resx	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Properties/Resources.resx	(revision 3816)
@@ -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>
Index: extensions/PiwigoLib/TestPiwigoLib/Properties/Settings.Designer.cs
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Properties/Settings.Designer.cs	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Properties/Settings.Designer.cs	(revision 3816)
@@ -0,0 +1,30 @@
+﻿//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.3082
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace TestPiwigoLib.Properties
+{
+
+
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.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;
+            }
+        }
+    }
+}
Index: extensions/PiwigoLib/TestPiwigoLib/Properties/Settings.settings
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/Properties/Settings.settings	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/Properties/Settings.settings	(revision 3816)
@@ -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>
Index: extensions/PiwigoLib/TestPiwigoLib/TestPiwigoLib.csproj
===================================================================
--- extensions/PiwigoLib/TestPiwigoLib/TestPiwigoLib.csproj	(revision 3816)
+++ extensions/PiwigoLib/TestPiwigoLib/TestPiwigoLib.csproj	(revision 3816)
@@ -0,0 +1,95 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{9B390DE8-884A-433D-828A-C7B969F19924}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>TestPiwigoLib</RootNamespace>
+    <AssemblyName>TestPiwigoLib</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </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>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <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="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form1.Designer.cs">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>
+    <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>
+    <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>
+    <ProjectReference Include="..\PiwigoLib\PiwigoLib.csproj">
+      <Project>{64C068C5-DBFE-4712-9081-B9100698F35C}</Project>
+      <Name>PiwigoLib</Name>
+    </ProjectReference>
+  </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>
Index: extensions/PiwigoLib/doc/ws.htm
===================================================================
--- extensions/PiwigoLib/doc/ws.htm	(revision 3816)
+++ extensions/PiwigoLib/doc/ws.htm	(revision 3816)
@@ -0,0 +1,402 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>PWG web service explorer</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script type="text/javascript" src="prototype.js" ></script>
+
+<script type="text/javascript">
+
+function setVisibility(id, vis)
+{
+  $(id).style.visibility = vis;
+}
+
+function dumpError(err)
+{
+	var s= 'Error ';
+	if ('string' === typeof err )
+	 s += err;
+	else
+	{
+    s += err.name+'<br/>';
+	 s += err.message;
+	 if (err.stack!=null)
+	 {//mozilla only
+	 	s += '<br/><small><pre>'+ err.stack + '</pre></small>';
+	 }
+	}
+  $("error").update(s);
+}
+
+var gServiceUrl;
+var gCachedMethods;
+
+Ajax.Responders.register({
+
+onException: function(req, err) {
+	try {
+		document.pwgError = err;
+		dumpError(err);
+	}
+	catch (e)
+	{
+		alert (err);
+		alert (err.message);
+	}
+},
+
+onComplete: function(req, transport) {
+	if (!req.responseIsSuccess())
+	{
+		var s = 'Completion failure\n' + transport.status + ' ' + transport.statusText;
+		if (transport.status>=300)
+		{
+			s += '\n';
+			s += transport.responseText.substr(0,1000);
+		}
+		dumpError(s);
+	}
+ }
+}
+);
+
+
+function pwgGetJsonResult(transport)
+{
+  var resp;
+  try {
+		eval('resp = ' + transport.responseText);
+	}
+	catch (e)
+	{
+		var s = e.message;
+		s += '\n' + transport.responseText.substr(0,1000).escapeHTML();
+		throw new Error( s );
+	}
+  if (resp==null || resp.result==null || resp.stat==null || resp.stat!='ok')
+  {
+    var s = 'JSON evaluation error';
+    if (resp)
+    {
+			if (resp.stat!=null) s+= '\n'+resp.stat;
+      if (resp.message!=null) s+= '\n'+ resp.message;
+    }
+    throw new Error(s);
+  }
+  return resp.result;
+}
+
+function pwgChangeUrl()
+{
+  $("error").update("");
+  setVisibility("methodListWrapper", "hidden");
+  $("methodList").update("");
+  setVisibility("methodWrapper", "hidden");
+  setVisibility("methodDetailWrapper", "hidden");
+
+  gServiceUrl = $F('ws_url');
+  gCachedMethods = new Hash();
+
+  try {
+		var ajaxReq = new Ajax.Request(
+				gServiceUrl,
+				{method:'get', parameters:'format=json&method=reflection.getMethodList',
+				 onSuccess: function (r) { onSuccess_getMethodList(r); }
+				}
+			)
+  }catch (e)
+  {
+    dumpError(e);
+  }
+  return false;
+}
+
+function onSuccess_getMethodList(transport)
+{
+	var result = pwgGetJsonResult(transport);
+	var ml = '';
+	for (var i=0; i<result.methods.length; i++)
+	{
+		ml += '<li><a href="#" onclick="return pwgSelectMethod(this.innerHTML)">'+ result.methods[i]+'</a></li>';
+	}
+	$("methodList").update(ml);
+	setVisibility("methodListWrapper", "visible");
+}
+
+function pwgSelectMethod(methodName)
+{
+  $("error").update("");
+  $("methodName").update(methodName);
+  setVisibility("methodDetailWrapper", "hidden");
+  setVisibility("methodWrapper", "visible");
+
+  if ( gCachedMethods[methodName] )
+    fillNewMethod( gCachedMethods[methodName] );
+  else
+  {
+    try {
+  		var ajaxReq = new Ajax.Request(
+  				gServiceUrl,
+  				{method:'get', parameters:'format=json&method=reflection.getMethodDetails&methodName='+methodName,
+  				 onSuccess: function (r) { onSuccess_getMethodDetails(r); }
+  				}
+  			)
+    }catch (e)
+    {
+      dumpError( e );
+    }
+  }
+  return false;
+}
+
+function onSuccess_getMethodDetails(transport)
+{
+	var result = pwgGetJsonResult(transport);
+  fillNewMethod( gCachedMethods[result.name] = result );
+}
+
+function fillNewMethod(method)
+{
+	var methodParamsElt = $("methodParams");
+	while (methodParamsElt.tBodies[0].rows.length)
+		methodParamsElt.tBodies[0].deleteRow(methodParamsElt.tBodies[0].rows.length-1);
+
+	if (method.params && method.params.length>0)
+	{
+  		for (var i=0; i<method.params.length; i++)
+  		{
+  			var row = methodParamsElt.tBodies[0].insertRow(-1);
+  			var isOptional = method.params[i].optional;
+  			var acceptArray = method.params[i].acceptArray;
+  			var defaultValue = method.params[i].defaultValue == null ? '' : method.params[i].defaultValue;
+
+  			row.insertCell(0).innerHTML = method.params[i].name;
+  			row.insertCell(1).innerHTML = '<span title="parameter is '+(isOptional ? 'optional':'required') +'">'+(isOptional ? '?':'*')+'</span>'
+          + (method.params[i].acceptArray ? ' <span title="parameter can be an array; use | (pipe) character to split values">[ ]</span>':'');
+  			row.insertCell(2).innerHTML = '<input id="methodParameterSend_'+i+'" type="checkbox" '+(isOptional ? '':'checked="checked"')+'/>';
+  			row.insertCell(3).innerHTML = '<input id="methodParameterValue_'+i+'"" value="'+defaultValue+'" style="width:99%" onchange="$(\'methodParameterSend_'+i+'\').checked=true;"/>';
+  		}
+ 	}
+	$("methodDescription").update(method.description);
+	setVisibility("methodDetailWrapper", "visible");
+}
+
+function pwgInvokeMethod( newWindow )
+{
+	var methodName = $('methodName').innerHTML;
+	var method = gCachedMethods[methodName];
+
+  var reqUrl = gServiceUrl;
+  reqUrl += "?format="+$F('responseFormat');
+
+  if ($('requestFormat').value == 'get')
+  {
+    reqUrl += "&method="+methodName;
+    for ( var i=0; i<method.params.length; i++)
+    {
+      if (! $('methodParameterSend_'+i).checked)
+        continue;
+
+      if ( method.params[i].acceptArray &&  $F('methodParameterValue_'+i).split('|').length > 1 )
+      {
+        $F('methodParameterValue_'+i).split('|').each(
+            function(v) {
+              reqUrl += '&'+method.params[i].name+'[]='+v;
+            }
+          );
+      }
+      else
+        reqUrl += '&'+method.params[i].name+'='+$F('methodParameterValue_'+i);
+    }
+    if ( !newWindow )
+      $("invokeFrame").src = reqUrl;
+    else
+      window.open(reqUrl);
+  }
+  else
+  {
+    var form = $("invokeForm");
+    form.action = reqUrl;
+    var t = '<input type="hidden" name="'+'method'+'" value="'+methodName+'"/>';
+    for ( var i=0; i<method.params.length; i++)
+    {
+      if (! $('methodParameterSend_'+i).checked)
+        continue;
+
+      if ( method.params[i].acceptArray &&  $F('methodParameterValue_'+i).split('|').length > 1 )
+      {
+        $F('methodParameterValue_'+i).split('|').each(
+            function(v) {
+              t += '<input type="hidden" name="'+method.params[i].name+'[]" value="'+v+'"/>';
+            }
+          );
+      }
+      else
+        t += '<input type="hidden" name="'+method.params[i].name+'" value="'+$F('methodParameterValue_'+i)+'"/>';
+    }
+    form.innerHTML = t;
+    form.target = newWindow ? "_blank" : "invokeFrame";
+    form.submit();
+  }
+  return false;
+}
+</script>
+
+
+<style>
+#methodListWrapper {
+  width: 13em;
+  float: left;
+  display: inline;
+  visibility: hidden;
+}
+
+#methodList {
+  padding-left: 10px;
+  margin-left: 15px;
+}
+
+#methodWrapper {
+  margin-left: 14em;
+  visibility: hidden;
+}
+
+#methodName {
+  margin-top: 0;
+  margin-bottom: 3px;
+}
+
+
+#error {
+  height: 90px;
+  overflow: scroll;
+  color: red;
+}
+
+#methodParams {
+  border-collapse: collapse;
+  font-size: small;
+}
+
+#methodParams input {
+  font-size: 90%;
+  border: 1px solid black;
+  text-indent: 2px;
+}
+
+
+a {
+  color: #02f;
+  background-color: white;
+  text-decoration: underline;
+}
+
+a:hover {
+  color: white;
+  background-color: #02f;
+  text-decoration: none;
+  cursor:pointer;
+}
+
+</style>
+
+</head>
+
+
+<body>
+
+<div>
+ <label>PWG Web service url
+  <input name="ws_url" id="ws_url" size="64"/>
+<script type="text/javascript">
+  var match = document.location.toString().match(/^(https?.*\/)tools\/ws\.html?$/);
+  if (match!=null) $('ws_url').value = match[1]+'ws.php';
+</script>
+ </label>
+ <a href="#" onclick="return pwgChangeUrl();">Go!</a>
+</div>
+
+<div id="error">
+</div>
+
+<div>
+
+<div id="methodListWrapper"><h2>Methods</h2>
+  <ul id="methodList">
+    <li><a href="#" onclick="return pwgSelectMethod(this.innerHTML)">getVersion</a></li>
+  </ul>
+</div>
+
+<div id="methodWrapper">
+  <h2 id="methodName"></h2>
+  <div id="methodDetailWrapper">
+
+    <table>
+    <tr style="vertical-align:top">
+
+    <td>
+      <div id="methodDescription"></div>
+      <table>
+        <tr>
+          <td>Request format:</td>
+          <td>
+            <select id="requestFormat">
+              <option value="get" selected="selected">GET</option>
+              <option value="post">POST</option>
+            </select>
+          </td>
+        </tr>
+
+        <tr>
+          <td>Response format:</td>
+          <td>
+            <select id="responseFormat">
+              <option value="rest" selected="selected">REST (xml)</option>
+              <option value="json">JSON</option>
+              <option value="php">PHP serial</option>
+              <option value="xmlrpc">XML RPC</option>
+            </select>
+          </td>
+        </tr>
+      </table>
+      <p>
+        <a href="#" onclick="return pwgInvokeMethod(false)">Invoke</a>
+        <a href="#" onclick="return pwgInvokeMethod(true)">Invoke (new Window)</a>
+      </p>
+    </td>
+
+
+    <td>
+      <table id="methodParams"  border="1" cellspacing="0" cellpadding="2px">
+        <thead>
+          <tr>
+            <td style="width:150px">Parameter</td>
+            <td>Extra</td>
+            <td>Send</td>
+            <td style="width:160px">Value</td>
+          </tr>
+        </thead>
+        <tbody>
+        </tbody>
+      </table>
+    </td>
+
+    </tr>
+    </table>
+
+		<div style="display:none;">
+			<!-- hiddenForm for POST -->
+			<form method="post" action="" target="invokeFrame" id="invokeForm">
+				<input type="submit" value="submit"/>
+			</form>
+		</div>
+
+    <iframe width="100%" height="400px" id="invokeFrame" name="invokeFrame" style="clear:both"></iframe>
+  </div> <!-- methodDetailWrapper -->
+</div> <!-- methodWrapper -->
+
+</div>
+
+</body>
+</html>
