public void Login(string username, string password) { fetcher.Username = username; fetcher.Password = password; try { bag = ContentCodeBag.ParseCodes(fetcher.Fetch("/content-codes")); ContentNode node = ContentParser.Parse(bag, fetcher.Fetch("/login")); ParseSessionId(node); FetchDatabases(); Refresh(); // FIXME - the update handling mechanism is currently disabled /* if (server_info.SupportsUpdate) { * update_running = true; * Thread thread = new Thread (UpdateLoop); * thread.IsBackground = true; * thread.Start (); * }*/ } catch (WebException e) { if (e.Response != null && (e.Response as HttpWebResponse).StatusCode == HttpStatusCode.Unauthorized) { throw new AuthenticationException("Username or password incorrect"); } else { throw new LoginException("Failed to login", e); } } catch (Exception e) { throw new LoginException("Failed to login", e); } }
private static ContentNode [] ParseChildren(ContentCodeBag bag, byte [] buffer, int offset, int length) { ArrayList children = new ArrayList(); int position = offset; while (position < offset + length) { children.Add(Parse(bag, buffer, null, ref position)); } return((ContentNode [])children.ToArray(typeof(ContentNode))); }
public static byte [] Write(ContentCodeBag bag, ContentNode node) { MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); Write(bag, node, writer); writer.Flush(); byte [] buf = stream.GetBuffer(); long len = stream.Length; writer.Close(); byte [] ret = new byte [len]; Array.Copy(buf, ret, len); return(ret); }
public static ContentNode Parse(ContentCodeBag bag, byte [] buffer) { return(Parse(bag, buffer, null)); }
public static ContentNode Parse(ContentCodeBag bag, byte [] buffer, string root) { int offset = 0; return(Parse(bag, buffer, root, ref offset)); }
public static ContentNode Parse(ContentCodeBag bag, byte [] buffer, string root, ref int offset) { ContentNode node = new ContentNode(); int num = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset)); ContentCode code; // This is a fix for iPhoto '08 which gives wrong content-type for dpap.databasecontainers (aply) if (num == 1634757753) { code = new ContentCode(); code.Name = "dpap.databasecontainers"; code.Type = ContentType.Container; } else { code = bag.Lookup(num); } if (code.Name.Equals("dpap.filedata")) { code.Type = ContentType.FileData; } if (code.Equals(ContentCode.Zero)) { // probably a buggy server. fallback to our internal code bag Console.WriteLine("fallback to internal code bag"); Console.WriteLine("Code number: " + num); throw new Exception("Content code not found!"); } int length = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset + 4)); if (code.Equals(ContentCode.Zero)) { throw new ContentException(String.Format("Failed to find content code for '{0}'. Data length is {1}", ContentCodeBag.GetStringFormat(num), length)); } node.Name = code.Name; Console.WriteLine("name = " + node.Name + "Code=" + code.Type.ToString() + " num=" + num); switch (code.Type) { case ContentType.Char: node.Value = (byte)buffer [offset + 8]; break; case ContentType.Short: node.Value = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, offset + 8)); break; case ContentType.SignedLong: case ContentType.Long: node.Value = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset + 8)); break; case ContentType.LongLong: node.Value = IPAddress.NetworkToHostOrder(BitConverter.ToInt64(buffer, offset + 8)); break; case ContentType.String: node.Value = Encoding.UTF8.GetString(buffer, offset + 8, length); break; case ContentType.Date: node.Value = Utility.ToDateTime(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset + 8))); break; case ContentType.Version: int major = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, offset + 8)); int minor = (int)buffer [offset + 10]; int micro = (int)buffer [offset + 11]; node.Value = new Version(major, minor, micro); break; case ContentType.Container: node.Value = ParseChildren(bag, buffer, offset + 8, length); break; case ContentType.FileData: node.Value = offset + 8; break; default: throw new ContentException(String.Format("Unknown content type '{0}' for '{1}'", code.Type, code.Name)); } offset += length + 8; if (root != null) { ContentNode root_node = node.GetChild(root); if (root_node == null) { throw new ContentException(String.Format("Could not find root node '{0}'", root)); } return(root_node); } else { return(node); } }
private static void Write(ContentCodeBag bag, ContentNode node, BinaryWriter writer) { ContentCode code = bag.Lookup(node.Name); if (code.Equals(ContentCode.Zero)) { throw new ContentException("Failed to get content code for: " + node.Name); } writer.Write(IPAddress.HostToNetworkOrder(code.Number)); switch (code.Type) { case ContentType.Char: writer.Write(IPAddress.HostToNetworkOrder(1)); writer.Write((byte)node.Value); break; case ContentType.Short: writer.Write(IPAddress.HostToNetworkOrder(2)); writer.Write(IPAddress.HostToNetworkOrder((short)node.Value)); break; case ContentType.SignedLong: case ContentType.Long: writer.Write(IPAddress.HostToNetworkOrder(4)); writer.Write(IPAddress.HostToNetworkOrder((int)node.Value)); break; case ContentType.LongLong: writer.Write(IPAddress.HostToNetworkOrder(8)); writer.Write(IPAddress.HostToNetworkOrder((long)node.Value)); break; case ContentType.String: byte [] data = Encoding.UTF8.GetBytes((string)node.Value); writer.Write(IPAddress.HostToNetworkOrder(data.Length)); writer.Write(data); break; case ContentType.Date: writer.Write(IPAddress.HostToNetworkOrder(4)); writer.Write(IPAddress.HostToNetworkOrder(Utility.FromDateTime((DateTime)node.Value))); break; case ContentType.Version: Version version = (Version)node.Value; writer.Write(IPAddress.HostToNetworkOrder(4)); writer.Write((short)IPAddress.HostToNetworkOrder((short)version.Major)); writer.Write((byte)version.Minor); writer.Write((byte)version.Build); break; case ContentType.FileData: // after "pfdt" we should send the file size and then immediately the file's contents // DEBUG //Console.WriteLine ("ContentWriter FileData!"); ContentNode [] nodes = (ContentNode [])node.Value; //Console.WriteLine (nodes [0].Value); writer.Write(IPAddress.HostToNetworkOrder((int)nodes [0].Value)); FileInfo info = new FileInfo((string)nodes [1].Value); //Console.WriteLine ("reading file " + nodes [1].Value + ", length=" +info.Length); FileStream stream = info.Open(FileMode.Open, FileAccess.Read, FileShare.Read); int offset = -1; using (BinaryReader reader = new BinaryReader(stream)) { if (offset > 0) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); } long count = 0; long len = info.Length; while (count < len) { byte [] buf = reader.ReadBytes(Math.Min(8192, (int)len - (int)count)); if (buf.Length == 0) { break; } writer.Write(buf); count += buf.Length; } } break; case ContentType.Container: MemoryStream child_stream = new MemoryStream(); BinaryWriter child_writer = new BinaryWriter(child_stream); foreach (ContentNode child in (ContentNode [])node.Value) { Write(bag, child, child_writer); } child_writer.Flush(); byte [] bytes = child_stream.GetBuffer(); int len = (int)child_stream.Length; writer.Write(IPAddress.HostToNetworkOrder(len)); writer.Write(bytes, 0, len); child_writer.Close(); break; default: Console.Error.WriteLine("Cannot write node of type: " + code.Type); break; } }
public static ContentCodeBag ParseCodes(byte [] buffer) { ContentCodeBag bag = new ContentCodeBag(); // add some codes to bootstrap us bag.AddCode("mccr", "dmap.contentcodesresponse", ContentType.Container); bag.AddCode("mdcl", "dmap.dictionary", ContentType.Container); bag.AddCode("mcnm", "dmap.contentcodesnumber", ContentType.Long); bag.AddCode("mcna", "dmap.contentcodesname", ContentType.String); bag.AddCode("mcty", "dmap.contentcodestype", ContentType.Short); bag.AddCode("mstt", "dmap.status", ContentType.Long); // some photo-specific codes // shouldn't be needed now bag.AddCode("ppro", "dpap.protocolversion", ContentType.Long); bag.AddCode("pret", "dpap.blah", ContentType.Container); bag.AddCode("avdb", "dpap.serverdatabases", ContentType.Container); bag.AddCode("aply", "dpap.databasecontainers", ContentType.Container); bag.AddCode("abpl", "dpap.baseplaylist", ContentType.Char); bag.AddCode("apso", "dpap.playlistsongs", ContentType.Container); bag.AddCode("pasp", "dpap.aspectratio", ContentType.String); bag.AddCode("adbs", "dpap.databasesongs", ContentType.Container); bag.AddCode("picd", "dpap.creationdate", ContentType.Long); bag.AddCode("pifs", "dpap.imagefilesize", ContentType.Long); bag.AddCode("pwth", "dpap.imagepixelwidth", ContentType.Long); bag.AddCode("phgt", "dpap.imagepixelheight", ContentType.Long); bag.AddCode("pcmt", "dpap.imagecomments", ContentType.String); bag.AddCode("prat", "dpap.imagerating", ContentType.Long); bag.AddCode("pimf", "dpap.imagefilename", ContentType.String); bag.AddCode("pfmt", "dpap.imageformat", ContentType.String); bag.AddCode("plsz", "dpap.imagelargefilesize", ContentType.Long); bag.AddCode("pfdt", "dpap.filedata", ContentType.FileData); ContentNode node = ContentParser.Parse(bag, buffer); foreach (ContentNode dictNode in (node.Value as ContentNode [])) { if (dictNode.Name != "dmap.dictionary") { continue; } ContentCode code = new ContentCode(); foreach (ContentNode item in (dictNode.Value as ContentNode [])) { switch (item.Name) { case "dmap.contentcodesnumber": code.Number = (int)item.Value; break; case "dmap.contentcodesname": code.Name = (string)item.Value; break; case "dmap.contentcodestype": code.Type = (ContentType)Enum.ToObject(typeof(ContentType), (short)item.Value); break; } } bag.codes [code.Number] = code; } return(bag); }