using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Web; using System.IO; using System.Web.UI; using Nuclex.Networking.Gallery3.Requests; namespace Nuclex.Networking.Gallery3 { /// Connects to a gallery installation using the gallery REST API public class Gallery : ConnectionUser { /// Connects to a Gallery 3 installation /// URL of the Gallery 3 installation /// API key for the user to connect as /// /// A new gallery connector through which the gallery can be accessed /// public static Gallery Connect(string galleryUrl, string apiKey) { return Connect(new RequestFactory(galleryUrl), apiKey); } /// Connects to a Gallery 3 installation /// /// Interface through which requests to the Gallery 3 installation are created /// /// API key for the user to connect as /// /// A new gallery connector through which the gallery can be accessed /// public static Gallery Connect(IRequestFactory requestFactory, string apiKey) { if (apiKey == null) { throw new ArgumentNullException("apiKey", "The API key must not be null"); } return connectInternal(requestFactory, apiKey); } /// Connects to a Gallery 3 installation as a guest user /// URL of the Gallery 3 installation /// /// A new gallery connector through which the gallery can be accessed /// /// /// This method is named differently instead of as an overload to Connect() to /// ensure it is not accidentally used. Without special preparations, Gallery3's /// REST API does not allow guest access. /// public static Gallery ConnectAsGuest(string galleryUrl) { return ConnectAsGuest(CreateRequestFactory(galleryUrl)); } /// Connects to a Gallery 3 installation as a guest user /// /// Interface through which requests to the Gallery 3 installation are created /// /// /// A new gallery connector through which the gallery can be accessed /// /// /// This method is named differently instead of as an overload to Connect() to /// ensure it is not accidentally used. Without special preparations, Gallery3's /// REST API does not allow guest access. /// public static Gallery ConnectAsGuest(IRequestFactory requestFactory) { return connectInternal(requestFactory, null); } /// Queries gallery for the REST API key of the specified user /// /// URL of the gallery base installation /// (for example, 'http://www.mydomain.com/gallery3/index.php') /// /// Name of the user whose REST API key will be retrieved /// Password for the user /// The REST API key for the specified user public static string QueryApiKey(string galleryUrl, string user, string password) { return QueryApiKey(CreateRequestFactory(galleryUrl), user, password); } /// Queries gallery for the REST API key of the specified user /// /// Interface through which requests to the Gallery 3 installation are created /// /// URL of the gallery base installation /// (for example, 'http://www.mydomain.com/gallery3/index.php') /// /// Name of the user whose REST API key will be retrieved /// Password for the user /// The REST API key for the specified user public static string QueryApiKey( IRequestFactory requestFactory, string user, string password ) { IRequest request = requestFactory.CreateRequest("rest"); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8"; request.AddHeader("X-Gallery-Request-Method", "post"); // Attach the url-encoded credentials we'll use to log in { StringBuilder builder = new StringBuilder(); builder.Append("user="); builder.Append(HttpUtility.UrlEncode(user)); builder.Append("&password="); builder.Append(HttpUtility.UrlEncode(password)); byte[] credentials = Encoding.UTF8.GetBytes(builder.ToString()); request.AttachContent(credentials); } // Execute the request and read its JSON response return request.GetJsonResponse(); } /// The root album in the gallery public Album RootAlbum { get { return this.rootAlbum; } } /// Creates the default request factory used for gallery requests /// Base URL of the gallery installation /// The newly created request factory internal static IRequestFactory CreateRequestFactory(string url) { return new RequestFactory(url); } /// Initializes a new gallery 3 connector /// /// Factory used to issue new requests to the gallery installation /// /// /// API key for the user the requests will run as /// /// JSON data for the gallery's root album private Gallery( IRequestFactory requestFactory, string apiKey, ref Responses.JsonItem rootAlbum ) : base(new GalleryConnection(requestFactory, apiKey)) { this.rootAlbum = new Album(Connection, ref rootAlbum); } /// Establishes a connection to a gallery installation /// /// Request factory that will be used to contact the gallery REST API /// /// /// API key of the user to access the gallery as. If this is null, /// a connection will be made as the guest user. /// /// A new gallery connector of the connection was successful private static Gallery connectInternal(IRequestFactory requestFactory, string apiKey) { IRequest request = requestFactory.CreateRequest("rest/item/1"); request.Method = "GET"; request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8"; request.AddHeader("X-Gallery-Request-Method", "get"); if (apiKey != null) { request.AddHeader("X-Gallery-Request-Key", apiKey); } // Read the response to our request. Because the java script serializer mapping // is non-strict, if this connector is used to connect to something else (or // the server implementation is changed), we only notice this by our fields not // being assigned. var item = request.GetJsonResponse(); if (item.Entity.Id != 1) { throw new WebException("Could not understand reply from remote host"); } return new Gallery(requestFactory, apiKey, ref item); } /// The root album in the gallery private Album rootAlbum; } } // namespace Nuclex.Networking.Gallery3