private void DownloadWorkFile(int workfile_id, string md5) { DBWorkFileView view = null; DBFile file = null; string filename; string mime; string compressed_mime; using (DB db = new DB()) { WebServiceLogin login = Authentication.CreateLogin(Request); filename = Request ["filename"]; if (!string.IsNullOrEmpty(md5)) // md5 lookup needs admin rights { Authentication.VerifyUserInRole(Context, db, login, Roles.Administrator, false); file = DBFile_Extensions.Find(db, md5); if (file == null) { throw new HttpException(404, "Could not find the file."); } mime = file.mime; filename = file.filename; compressed_mime = file.compressed_mime; } else { view = DBWorkFileView_Extensions.Find(db, workfile_id); if (view == null) { throw new HttpException(404, "Could not find the file."); } if (view.@internal) // internal files need admin rights { Authentication.VerifyUserInRole(Context, db, login, Roles.Administrator, false); } else { Authentication.VerifyAnonymousAccess(Context, db, login); } if (!string.IsNullOrEmpty(filename)) { file = DBWork_Extensions.GetFile(db, view.work_id, filename, false); if (file == null) { throw new HttpException(404, string.Format("Could not find the filename '{0}'", filename)); } mime = file.mime; compressed_mime = file.compressed_mime; md5 = file.md5; view = null; } else { mime = view.mime; filename = view.filename; compressed_mime = view.compressed_mime; } } Response.ContentType = mime; Response.AppendHeader("Content-Disposition", "filename=\"" + Path.GetFileName(filename) + "\""); // any access rights verified, serve the file if (view != null) { if (view.file_file_id == null) { DownloadMd5(view.md5); } else { using (Stream str = db.Download(view)) { DownloadStream(str, compressed_mime); } } } else { DownloadFile(db, file); } } }
private static void ExecuteRequest(object state) { NetworkStream stream = null; byte [] buffer; int id = counter++; string tmpfile = null; TcpClient client = null; BinaryReader reader = null; BinaryWriter writer = null; string remote_ip; WebServiceLogin login = new WebServiceLogin(); try { buffer = new byte [1024]; client = (TcpClient)state; stream = client.GetStream(); stream.ReadTimeout = (int)TimeSpan.FromMinutes(5).TotalMilliseconds; stream.WriteTimeout = stream.ReadTimeout; reader = new BinaryReader(stream); writer = new BinaryWriter(stream); remote_ip = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString(); /* Format: * Field Length in bytes Description * version 1 1 * name_length 1 * name <name_length> * password_length 1 * password <password_length> * work_id 4 The Work.id field in the database * file_count 2 * reserved 8 * * < file #1> * marker 12 'MonkeyWrench' * md5 16 * flags 1 1 = compressed, 2 = hidden * filename_length 1 * filename <filename_length> * <client waits for answer, either type 2 or 4, type 2: server already has data, type 4: server does not have data> * [type: 4] compressed_mime_length 1 * [type: 4] compressed_mime <compressed_mime_length> * [type: 4] content_length 4 * [type: 4] content <content_length> * [type: 4] <client waits for response, type 2> * * < file #2 > * ... * * The response data has this format: * version 1 * type 1 1 = everything OK, 2 = file received OK, 3 = error, 4 = send file * depending on type, here are the subsequent fields: * [type: 3] message_length 2 * [type: 3] message <message length> * */ byte version = reader.ReadByte(); byte name_length = reader.ReadByte(); login.User = ReadString(reader, buffer, name_length); byte password_length = reader.ReadByte(); login.Password = ReadString(reader, buffer, password_length); login.Ip4 = remote_ip; int work_id = reader.ReadInt32(); ushort file_count = reader.ReadUInt16(); reader.ReadInt64(); Logger.Log(2, "Upload.ExecuteRequest (): {0} version: {1} work_id: {2} file count: {3} remote ip: {4}", id, version, work_id, file_count, client.Client.RemoteEndPoint.ToString()); using (DB db = new DB()) { Authentication.VerifyUserInRole(remote_ip, db, login, Roles.BuildBot, true); for (ushort i = 0; i < file_count; i++) { byte [] md5 = new byte [16]; byte flags; bool hidden; byte filename_length; byte compressed_mime_length; int content_length; string filename; string compressed_mime; string marker; marker = ReadString(reader, buffer, 12); if (marker != "MonkeyWrench") { throw new Exception(string.Format("Didn't get marker 'MonkeyWrench' at start of file, got '{0}'", marker)); } reader.Read(md5, 0, 16); flags = reader.ReadByte(); filename_length = reader.ReadByte(); filename = ReadString(reader, buffer, filename_length); hidden = (flags & 0x2) == 0x2; // compressed = (flags & 0x1) == 0x1; Logger.Log(2, "Upload.ExecuteRequest (): {0} file #{1}: filename: '{2}' ", id, i + 1, filename); DBFile file = DBFile_Extensions.Find(db, FileUtilities.MD5BytesToString(md5)); if (file == null) { Logger.Log(2, "Upload.ExecuteRequest (): {0} file #{1} must be sent, sending 'send file' response", id, i + 1); // Write 'send file' writer.Write((byte)1); // version writer.Write((byte)4); // type (4 = send file) writer.Flush(); compressed_mime_length = reader.ReadByte(); compressed_mime = ReadString(reader, buffer, compressed_mime_length); content_length = reader.ReadInt32(); Logger.Log(2, "Upload.ExecuteRequest (): {0} file #{1} content_length: {2} compressed_mime: '{3}' reading...", id, i + 1, content_length, compressed_mime); int bytes_left = content_length; tmpfile = Path.GetTempFileName(); using (FileStream fs = new FileStream(tmpfile, FileMode.Open, FileAccess.Write, FileShare.Read)) { while (bytes_left > 0) { int to_read = Math.Min(bytes_left, buffer.Length); int read = reader.Read(buffer, 0, to_read); if (read == 0) { throw new Exception(string.Format("Failed to read {0} bytes, {1} bytes left", content_length, bytes_left)); } fs.Write(buffer, 0, read); bytes_left -= read; } } Logger.Log(2, "Upload.ExecuteRequest (): {0} file #{1} received, uploading '{2}' to database", id, i + 1, tmpfile); file = db.Upload(FileUtilities.MD5BytesToString(md5), tmpfile, filename, Path.GetExtension(filename), hidden, compressed_mime); } else { Logger.Log(2, "Upload.ExecuteRequest (): {0} file #{1} already in database, not uploading", id, i + 1); } DBWork work = DBWork_Extensions.Create(db, work_id); work.AddFile(db, file, filename, hidden); // Write 'file recieved OK' writer.Write((byte)1); // version writer.Write((byte)2); // type (2 = file received OK) writer.Flush(); Logger.Log(2, "Upload.ExecuteRequest (): {0} {1} uploaded successfully", id, filename); } } // Write 'everything OK' writer.Write((byte)1); // version writer.Write((byte)1); // type (1 = everything OK) writer.Flush(); Logger.Log(2, "Upload.ExecuteRequest (): {0} completed", id); } catch (Exception ex) { try { string msg = ex.ToString(); byte [] msg_buffer = UTF8Encoding.UTF8.GetBytes(msg); writer.Write((byte)1); // version writer.Write((byte)3); // type (3 = error) writer.Write((ushort)Math.Min(msg_buffer.Length, ushort.MaxValue)); // message_length writer.Write(msg_buffer, 0, Math.Min(msg_buffer.Length, ushort.MaxValue)); // message stream.Flush(); } catch (Exception ex2) { Logger.Log("Upload.ExecuteRequest (): {0} Failed to send exception to client: {1}", id, ex2.Message); } Logger.Log("Upload.ExecuteRequest (): {0} {1}", id, ex); } finally { if (tmpfile != null) { FileUtilities.TryDeleteFile(tmpfile); } try { client.Close(); } catch { // Ignore } } }