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; }
internal static ServerInfo FromNode(ContentNode node) { ServerInfo info = new ServerInfo (); if (node.Name != "dmap.serverinforesponse") return null; foreach (ContentNode child in (node.Value as ContentNode [])) { switch (child.Name) { case "dmap.itemname": info.Name = (string) child.Value; break; case "dmap.authenticationmethod": info.AuthenticationMethod = (AuthenticationMethod) child.Value; break; case "dmap.supportsupdate": info.SupportsUpdate = (byte) child.Value == 1; break; } } return info; }
public void DownloadPhoto(Photo photo, string dest) { /* BinaryWriter writer = new BinaryWriter (File.Open (dest, FileMode.Create)); * MemoryStream data = new MemoryStream (); * try { * long len; * using (BinaryReader reader = new BinaryReader (StreamPhoto (photo, out len))) { * int count = 0; * byte [] buf = new byte [chunk_length]; * * // Skip the header * //count = reader.Read (buf,0,89); * * //if (count < 89) * // count+=reader.Read (buf,0,89-count); * * while (true) { * buf = reader.ReadBytes (8192); * if (buf.Length == 0) * break; * * data.Write (buf, 0, buf.Length); * //Console.Write (buf.); * } * */ /* do { * count = reader.Read (buf, 0, chunk_length); * writer.Write (buf, 0, count); * data.Write (buf, 0, count); * } while (count != 0); */ /*data.Flush (); * * ContentNode node = ContentParser.Parse (client.Bag, data.GetBuffer ()); * node.Dump (); * reader.Close (); * * } * } finally { * data.Close (); * * writer.Close (); * }*/ // maybe use FetchResponse to get a stream and feed it to pixbuf? byte [] photos_data = client.Fetcher.Fetch(String.Format("/databases/{0}/items", id), String.Format("meta=dpap.thumb,dpap.filedata&query=('dmap.itemid:{0}')", photo.Id)); ContentNode node = ContentParser.Parse(client.Bag, photos_data); // DEBUG Console.WriteLine("About to dump the photo!"); node.Dump(); ContentNode filedata_node = node.GetChild("dpap.filedata"); Console.WriteLine("Photo starts at index " + filedata_node.Value); BinaryWriter writer = new BinaryWriter(File.Open(dest, FileMode.Create)); int count = 0; int off = System.Int32.Parse(filedata_node.Value.ToString()); byte [] photo_buf; MemoryStream data = new MemoryStream(); writer.Write(photos_data, (int)off, (int)photos_data.Length - off); data.Position = 0; // Gdk.Pixbuf pb = new Gdk.Pixbuf (data); data.Close(); Console.Write("Written " + count + " out of " + (photos_data.Length - off)); }
private void RefreshAlbums(string revquery) { byte [] albums_data; try { albums_data = client.Fetcher.Fetch(String.Format("/databases/{0}/containers", id), "meta=dpap.aspectratio,dmap.itemid,dmap.itemname,dpap.imagefilename,dpap.imagefilesize,dpap.creationdate,dpap.imagepixelwidth,dpap.imagepixelheight,dpap.imageformat,dpap.imagerating,dpap.imagecomments,dpap.imagelargefilesize&type=photo"); } catch (WebException) { return; } ContentNode albums_node = ContentParser.Parse(client.Bag, albums_data); // DEBUG data albums_node.Dump(); Console.WriteLine("after dump!"); if (IsUpdateResponse(albums_node)) { return; } // handle album additions/changes ArrayList plids = new ArrayList(); if (albums_node.GetChild("dmap.listing") == null) { return; } foreach (ContentNode albumNode in (ContentNode [])albums_node.GetChild("dmap.listing").Value) { // DEBUG Console.WriteLine("foreach loop"); Album pl = Album.FromNode(albumNode); if (pl != null) { plids.Add(pl.Id); Album existing = LookupAlbumById(pl.Id); if (existing == null) { AddAlbum(pl); } else { existing.Update(pl); } } } // DEBUG Console.WriteLine("delete albums that don't exist"); // delete albums that no longer exist foreach (Album pl in new List <Album> (albums)) { if (!plids.Contains(pl.Id)) { RemoveAlbum(pl); } } plids = null; // DEBUG Console.WriteLine("Add/remove photos in the albums"); // add/remove photos in the albums foreach (Album pl in albums) { byte [] album_photos_data = client.Fetcher.Fetch(String.Format("/databases/{0}/containers/{1}/items", id, pl.Id), "meta=dpap.aspectratio,dmap.itemid,dmap.itemname,dpap.imagefilename,dpap.imagefilesize,dpap.creationdate,dpap.imagepixelwidth,dpap.imagepixelheight,dpap.imageformat,dpap.imagerating,dpap.imagecomments,dpap.imagelargefilesize&type=photo"); ContentNode album_photos_node = ContentParser.Parse(client.Bag, album_photos_data); if (IsUpdateResponse(album_photos_node)) { return; } if ((byte)album_photos_node.GetChild("dmap.updatetype").Value == 1) { // handle album photo deletions ContentNode delete_list = album_photos_node.GetChild("dmap.deletedidlisting"); if (delete_list != null) { foreach (ContentNode deleted in (ContentNode [])delete_list.Value) { int index = pl.LookupIndexByContainerId((int)deleted.Value); if (index < 0) { continue; } pl.RemoveAt(index); } } } // add new photos, or reorder existing ones int plindex = 0; foreach (ContentNode pl_photo_node in (ContentNode [])album_photos_node.GetChild("dmap.listing").Value) { Photo plphoto = null; int container_id = 0; Photo.FromAlbumNode(this, pl_photo_node, out plphoto, out container_id); if (pl [plindex] != null && pl.GetContainerId(plindex) != container_id) { pl.RemoveAt(plindex); pl.InsertPhoto(plindex, plphoto, container_id); } else if (pl [plindex] == null) { pl.InsertPhoto(plindex, plphoto, container_id); } plindex++; } } }
private bool IsUpdateResponse(ContentNode node) { return(node.Name == "dmap.updateresponse"); }
internal Database(Client client, ContentNode dbNode) : this() { this.client = client; Parse(dbNode); }
private bool IsUpdateResponse(ContentNode node) { return node.Name == "dmap.updateresponse"; }
public void WriteResponse(Socket client, ContentNode node) { WriteResponse (client, HttpStatusCode.OK, ContentWriter.Write (ContentCodeBag.Default, node)); }
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; }
internal static Album FromNode(ContentNode node) { Album pl = new Album (); foreach (ContentNode child in (ContentNode []) node.Value) { switch (child.Name) { case "dpap.baseplaylist": return null; case "dmap.itemid": pl.Id = (int) child.Value; break; case "dmap.itemname": pl.Name = (string) child.Value; break; default: break; } } return pl; }
internal bool OnHandleRequest(Socket client, string username, string path, NameValueCollection query, int range) { string photoQuery; if (query ["query"] != null) { photoQuery = query ["query"]; } else { photoQuery = ""; } int session = 0; if (query ["session-id"] != null) { session = Int32.Parse(query ["session-id"]); } /* if (!sessions.ContainsKey (session) && path != "/server-info" && path != "/content-codes" && * path != "/login") { * ws.WriteResponse (client, HttpStatusCode.Forbidden, "invalid session id"); * return true; * } */ if (session != 0) { sessions [session].LastActionTime = DateTime.Now; } int clientRev = 0; if (query ["revision-number"] != null) { clientRev = Int32.Parse(query ["revision-number"]); } int delta = 0; if (query ["delta"] != null) { delta = Int32.Parse(query ["delta"]); } // DEBUG data Console.WriteLine("Before returning resources for path " + path + ", meta " + query ["meta"] + " query " + photoQuery); if (dbItemsRegex.IsMatch(path)) //&& photoQuery.Length==0 { Console.WriteLine("\tThis is a database/items request!"); } if (path == "/server-info") { ws.WriteResponse(client, GetServerInfoNode()); } else if (path == "/content-codes") { ws.WriteResponse(client, ContentCodeBag.Default.ToNode()); } else if (path == "/login") { ExpireSessions(); if (maxUsers > 0 && sessions.Count + 1 > maxUsers) { ws.WriteResponse(client, HttpStatusCode.ServiceUnavailable, "too many users"); return(true); } session = random.Next(); User user = new User(DateTime.Now, (client.RemoteEndPoint as IPEndPoint).Address, username); lock (sessions) { sessions [session] = user; } ws.WriteResponse(client, GetLoginNode(session)); OnUserLogin(user); } else if (path == "/logout") { Console.WriteLine("logout!"); User user = sessions [session]; lock (sessions) { sessions.Remove(session); } ws.WriteResponse(client, HttpStatusCode.OK, new byte [0]); OnUserLogout(user); return(false); } else if (path == "/databases") { Console.WriteLine("path==/databases"); ws.WriteResponse(client, GetDatabasesNode()); } else if (dbItemsRegex.IsMatch(path) && photoQuery.Length == 0) //&& !dbPhotoRegex.IsMatch (query ["query"])) { { Console.WriteLine("dbItemsRegex, query=" + query ["query"] + " meta=" + query ["meta"]); int dbid = Int32.Parse(dbItemsRegex.Match(path).Groups [1].Value); Database curdb = revmgr.GetDatabase(clientRev, dbid); if (curdb == null) { ws.WriteResponse(client, HttpStatusCode.BadRequest, "invalid database id"); return(true); } ArrayList deletedIds = new ArrayList(); if (delta > 0) { Database olddb = revmgr.GetDatabase(clientRev - delta, dbid); if (olddb != null) { foreach (Photo photo in olddb.Photos) { if (curdb.LookupPhotoById(photo.Id) == null) { deletedIds.Add(photo.Id); } } } } ContentNode node = curdb.ToPhotosNode(query ["meta"].Split(','), (int [])deletedIds.ToArray(typeof(int))); ws.WriteResponse(client, node); } else if (dbPhotoRegex.IsMatch(photoQuery)) { Console.WriteLine("dbPhotoRegex"); Console.WriteLine("dbPhotosRegex, query=" + query ["query"] + " meta=" + query ["meta"]); string [] photoIds = query ["query"].Split(','); Match match = dbPhotoRegex0.Match(path); int dbid = Int32.Parse(match.Groups [1].Value); int photoid = 0; //match = dbPhotoRegex.Match (photoQuery); Database db = revmgr.GetDatabase(clientRev, dbid); if (db == null) { ws.WriteResponse(client, HttpStatusCode.BadRequest, "invalid database id"); return(true); } ArrayList photoNodes = new ArrayList(); Photo photo = db.LookupPhotoById(1); foreach (string photoId in photoIds) { match = dbPhotoRegex.Match(photoId); photoid = Int32.Parse(match.Groups [1].Value); photo = db.LookupPhotoById(photoid); photoNodes.Add(photo.ToFileData(query ["meta"].Contains("dpap.thumb"))); // DEBUG //Console.WriteLine ("Requested photo id=" + photoid); } ArrayList children = new ArrayList(); children.Add(new ContentNode("dmap.status", 200)); children.Add(new ContentNode("dmap.updatetype", (byte)0)); children.Add(new ContentNode("dmap.specifiedtotalcount", 2)); children.Add(new ContentNode("dmap.returnedcount", 2)); children.Add(new ContentNode("dmap.listing", photoNodes)); ContentNode dbsongs = new ContentNode("dpap.databasesongs", children); if (photo == null) { ws.WriteResponse(client, HttpStatusCode.BadRequest, "invalid photo id"); return(true); } try { try { if (PhotoRequested != null) { PhotoRequested(this, new PhotoRequestedArgs(username, (client.RemoteEndPoint as IPEndPoint).Address, db, photo)); } } catch {} if (photo.FileName != null) { // DEBUG //Console.WriteLine ("photo.Filename != null" + query ["meta"].Split (',') [0]); //ContentNode node = photo.ToFileData (); //node.Dump (); ws.WriteResponse(client, dbsongs); } else if (db.Client != null) { Console.WriteLine("db.Client != null"); long photoLength = 0; Stream photoStream = db.StreamPhoto(photo, out photoLength); try { ws.WriteResponseStream(client, photoStream, photoLength); } catch (IOException) { Console.WriteLine("IOException!"); } } else { Console.WriteLine("Else - internal error"); ws.WriteResponse(client, HttpStatusCode.InternalServerError, "no file"); } } finally { // commented out because it breaks the connection after sending a hires photo // client.Close() } } else if (dbContainersRegex.IsMatch(path)) { int dbid = Int32.Parse(dbContainersRegex.Match(path).Groups [1].Value); Database db = revmgr.GetDatabase(clientRev, dbid); if (db == null) { ws.WriteResponse(client, HttpStatusCode.BadRequest, "invalid database id"); return(true); } ws.WriteResponse(client, db.ToAlbumsNode()); } else if (dbContainerItemsRegex.IsMatch(path)) { // DEBUG Console.WriteLine("ContainerItems ! path=" + path); Match match = dbContainerItemsRegex.Match(path); int dbid = Int32.Parse(match.Groups [1].Value); int plid = Int32.Parse(match.Groups [2].Value); Database curdb = revmgr.GetDatabase(clientRev, dbid); if (curdb == null) { ws.WriteResponse(client, HttpStatusCode.BadRequest, "invalid database id"); return(true); } Album curpl = curdb.LookupAlbumById(plid); if (curdb == null) { ws.WriteResponse(client, HttpStatusCode.BadRequest, "invalid playlist id"); return(true); } // DEBUG Console.WriteLine("db and album ready!"); ArrayList deletedIds = new ArrayList(); if (delta > 0) { Database olddb = revmgr.GetDatabase(clientRev - delta, dbid); if (olddb != null) { Album oldpl = olddb.LookupAlbumById(plid); if (oldpl != null) { IList <Photo> oldplPhotos = oldpl.Photos; for (int i = 0; i < oldplPhotos.Count; i++) { int id = oldpl.GetContainerId(i); if (curpl.LookupIndexByContainerId(id) < 0) { deletedIds.Add(id); } } } } } Console.WriteLine("About to send response... meta=" + query["meta"]); curpl.ToPhotosNode(query ["meta"].Split(',')).Dump(); ws.WriteResponse(client, curpl.ToPhotosNode(query ["meta"].Split(','))); //, (int []) deletedIds.ToArray (typeof (int)))); } else if (path == "/update") { int retrev; lock (revmgr) { // if they have the current revision, wait for a change if (clientRev == revmgr.Current) { Monitor.Wait(revmgr); } retrev = revmgr.Current; } if (!running) { ws.WriteResponse(client, HttpStatusCode.NotFound, "server has been stopped"); } else { ws.WriteResponse(client, GetUpdateNode(retrev)); } } else { ws.WriteResponse(client, HttpStatusCode.Forbidden, "GO AWAY"); } return(true); }
public void WriteResponse(Socket client, ContentNode node) { WriteResponse(client, HttpStatusCode.OK, ContentWriter.Write(ContentCodeBag.Default, node)); }
private int GetCurrentRevision() { ContentNode rev_node = ContentParser.Parse(bag, fetcher.Fetch("/update"), "dmap.serverrevision"); return((int)rev_node.Value); }
private void ParseSessionId(ContentNode node) { fetcher.SessionId = (int)node.GetChild("dmap.sessionid").Value; }
private void Parse(ContentNode dbNode) { foreach (ContentNode item in (ContentNode []) dbNode.Value) { switch (item.Name) { case "dmap.itemid": id = (int) item.Value; break; case "dmap.persistentid": persistent_id = (long) item.Value; break; case "dmap.itemname": name = (string) item.Value; break; default: break; } } }
internal bool OnHandleRequest(Socket client, string username, string path, NameValueCollection query, int range) { string photoQuery; if (query ["query"] != null) photoQuery = query ["query"]; else photoQuery = ""; int session = 0; if (query ["session-id"] != null) { session = Int32.Parse (query ["session-id"]); } /* if (!sessions.ContainsKey (session) && path != "/server-info" && path != "/content-codes" && path != "/login") { ws.WriteResponse (client, HttpStatusCode.Forbidden, "invalid session id"); return true; } */ if (session != 0) { sessions [session].LastActionTime = DateTime.Now; } int clientRev = 0; if (query ["revision-number"] != null) { clientRev = Int32.Parse (query ["revision-number"]); } int delta = 0; if (query ["delta"] != null) { delta = Int32.Parse (query ["delta"]); } // DEBUG data Console.WriteLine ("Before returning resources for path " + path + ", meta " + query ["meta"] + " query " + photoQuery); if (dbItemsRegex.IsMatch (path)) //&& photoQuery.Length==0 Console.WriteLine ("\tThis is a database/items request!"); if (path == "/server-info") { ws.WriteResponse (client, GetServerInfoNode ()); } else if (path == "/content-codes") { ws.WriteResponse (client, ContentCodeBag.Default.ToNode ()); } else if (path == "/login") { ExpireSessions (); if (maxUsers > 0 && sessions.Count + 1 > maxUsers) { ws.WriteResponse (client, HttpStatusCode.ServiceUnavailable, "too many users"); return true; } session = random.Next (); User user = new User (DateTime.Now, (client.RemoteEndPoint as IPEndPoint).Address, username); lock (sessions) { sessions [session] = user; } ws.WriteResponse (client, GetLoginNode (session)); OnUserLogin (user); } else if (path == "/logout") { Console.WriteLine("logout!"); User user = sessions [session]; lock (sessions) { sessions.Remove (session); } ws.WriteResponse (client, HttpStatusCode.OK, new byte [0]); OnUserLogout (user); return false; } else if (path == "/databases") { Console.WriteLine ("path==/databases"); ws.WriteResponse (client, GetDatabasesNode ()); } else if (dbItemsRegex.IsMatch (path) && photoQuery.Length==0 ){ //&& !dbPhotoRegex.IsMatch (query ["query"])) { Console.WriteLine ("dbItemsRegex, query=" + query ["query"] + " meta=" + query ["meta"]); int dbid = Int32.Parse (dbItemsRegex.Match (path).Groups [1].Value); Database curdb = revmgr.GetDatabase (clientRev, dbid); if (curdb == null) { ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id"); return true; } ArrayList deletedIds = new ArrayList (); if (delta > 0) { Database olddb = revmgr.GetDatabase (clientRev - delta, dbid); if (olddb != null) { foreach (Photo photo in olddb.Photos) { if (curdb.LookupPhotoById (photo.Id) == null) deletedIds.Add (photo.Id); } } } ContentNode node = curdb.ToPhotosNode (query ["meta"].Split (','), (int []) deletedIds.ToArray (typeof (int))); ws.WriteResponse (client, node); } else if (dbPhotoRegex.IsMatch (photoQuery)) { Console.WriteLine ("dbPhotoRegex"); Console.WriteLine ("dbPhotosRegex, query=" + query ["query"] + " meta=" + query ["meta"]); string [] photoIds = query ["query"].Split (','); Match match = dbPhotoRegex0.Match (path); int dbid = Int32.Parse (match.Groups [1].Value); int photoid = 0; //match = dbPhotoRegex.Match (photoQuery); Database db = revmgr.GetDatabase (clientRev, dbid); if (db == null) { ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id"); return true; } ArrayList photoNodes = new ArrayList (); Photo photo = db.LookupPhotoById (1); foreach (string photoId in photoIds) { match = dbPhotoRegex.Match (photoId); photoid = Int32.Parse (match.Groups [1].Value); photo = db.LookupPhotoById (photoid); photoNodes.Add (photo.ToFileData (query ["meta"].Contains ("dpap.thumb"))); // DEBUG //Console.WriteLine ("Requested photo id=" + photoid); } ArrayList children = new ArrayList (); children.Add (new ContentNode ("dmap.status", 200)); children.Add (new ContentNode ("dmap.updatetype", (byte) 0)); children.Add (new ContentNode ("dmap.specifiedtotalcount", 2)); children.Add (new ContentNode ("dmap.returnedcount", 2)); children.Add (new ContentNode ("dmap.listing", photoNodes)); ContentNode dbsongs = new ContentNode ("dpap.databasesongs", children); if (photo == null) { ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid photo id"); return true; } try { try { if (PhotoRequested != null) PhotoRequested (this, new PhotoRequestedArgs (username, (client.RemoteEndPoint as IPEndPoint).Address, db, photo)); } catch {} if (photo.FileName != null) { // DEBUG //Console.WriteLine ("photo.Filename != null" + query ["meta"].Split (',') [0]); //ContentNode node = photo.ToFileData (); //node.Dump (); ws.WriteResponse (client, dbsongs); } else if (db.Client != null) { Console.WriteLine ("db.Client != null"); long photoLength = 0; Stream photoStream = db.StreamPhoto (photo, out photoLength); try { ws.WriteResponseStream (client, photoStream, photoLength); } catch (IOException) { Console.WriteLine("IOException!"); } } else { Console.WriteLine ("Else - internal error"); ws.WriteResponse (client, HttpStatusCode.InternalServerError, "no file"); } } finally { // commented out because it breaks the connection after sending a hires photo // client.Close() } } else if (dbContainersRegex.IsMatch (path)) { int dbid = Int32.Parse (dbContainersRegex.Match (path).Groups [1].Value); Database db = revmgr.GetDatabase (clientRev, dbid); if (db == null) { ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id"); return true; } ws.WriteResponse (client, db.ToAlbumsNode ()); } else if (dbContainerItemsRegex.IsMatch (path)) { // DEBUG Console.WriteLine ("ContainerItems ! path=" + path); Match match = dbContainerItemsRegex.Match (path); int dbid = Int32.Parse (match.Groups [1].Value); int plid = Int32.Parse (match.Groups [2].Value); Database curdb = revmgr.GetDatabase (clientRev, dbid); if (curdb == null) { ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id"); return true; } Album curpl = curdb.LookupAlbumById (plid); if (curdb == null) { ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid playlist id"); return true; } // DEBUG Console.WriteLine("db and album ready!"); ArrayList deletedIds = new ArrayList (); if (delta > 0) { Database olddb = revmgr.GetDatabase (clientRev - delta, dbid); if (olddb != null) { Album oldpl = olddb.LookupAlbumById (plid); if (oldpl != null) { IList<Photo> oldplPhotos = oldpl.Photos; for (int i = 0; i < oldplPhotos.Count; i++) { int id = oldpl.GetContainerId (i); if (curpl.LookupIndexByContainerId (id) < 0) { deletedIds.Add (id); } } } } } Console.WriteLine("About to send response... meta=" + query["meta"]); curpl.ToPhotosNode (query ["meta"].Split (',')).Dump (); ws.WriteResponse (client, curpl.ToPhotosNode (query ["meta"].Split (','))); //, (int []) deletedIds.ToArray (typeof (int)))); } else if (path == "/update") { int retrev; lock (revmgr) { // if they have the current revision, wait for a change if (clientRev == revmgr.Current) { Monitor.Wait (revmgr); } retrev = revmgr.Current; } if (!running) { ws.WriteResponse (client, HttpStatusCode.NotFound, "server has been stopped"); } else { ws.WriteResponse (client, GetUpdateNode (retrev)); } } else { ws.WriteResponse (client, HttpStatusCode.Forbidden, "GO AWAY"); } return true; }
private ContentNode GetDatabasesNode() { ArrayList databaseNodes = new ArrayList (); List<Database> dbs = revmgr.GetRevision (revmgr.Current); if (dbs != null) { foreach (Database db in revmgr.GetRevision (revmgr.Current)) { databaseNodes.Add (db.ToDatabaseNode ()); } } ContentNode node = new ContentNode ("dpap.serverdatabases", new ContentNode ("dmap.status", 200), new ContentNode ("dmap.updatetype", (byte) 0), new ContentNode ("dmap.specifiedtotalcount", databases.Count), new ContentNode ("dmap.returnedcount", databases.Count), new ContentNode ("dmap.listing", databaseNodes)); return node; }
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); }
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 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; } }
internal Database(Client client, ContentNode dbNode) : this() { this.client = client; Parse (dbNode); }