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;
        }
        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;
            }
        }
Exemple #3
0
        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 ();

                if (serverInfo.SupportsUpdate) {
                    updateRunning = true;
                    Thread thread = new Thread (UpdateLoop);
                    thread.Name = "DAAP";
                    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 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;
        }