public static void AddJob(JobInfo info)
        {
            Logger.DebugFormat("adding print job {0}", info.JobID);
            lock (ManagementLock)
            {
                JobDictionary[info.JobID] = info;

                WriteJobs();
            }
        }
        static void Main(string[] args)
        {
            // parse args
            if (args.Length < 4 || args.Length > 6)
            {
                UsageAndExit();
            }

            var pseudoUri = new Uri(string.Format("lpd://{0}", args[0]));
            var host = pseudoUri.Host;
            var port = 515;
            if (!pseudoUri.IsDefaultPort)
            {
                port = pseudoUri.Port;
            }

            var queue = args[1];
            var user = args[2];
            var localFilename = args[3];
            var remoteFilename = (args.Length > 4) ? args[4] : Path.GetFileName(localFilename);
            var localHostname = (args.Length > 5) ? args[5] : System.Net.Dns.GetHostName().Split('.')[0];

            // sanity check
            var fileInfo = new FileInfo(localFilename);
            if (!fileInfo.Exists)
            {
                Console.Error.WriteLine("Local file '{0}' does not exist!", localFilename);
                UsageAndExit();
            }
            var fileSize = fileInfo.Length;

            // prepare the JobInfo
            var jobInfo = new JobInfo
            {
                DataFilePath = localFilename,
                DataFileSize = fileSize,
                DocumentName = remoteFilename,
                HostName = localHostname,
                Status = JobInfo.JobStatus.ReadyToPrint,
                TimeOfArrival = DateTimeOffset.Now,
                UserName = user
            };

            // prepare the sender
            var sender = new LpdSender
            {
                Host = host,
                Port = port,
                QueueName = queue
            };
            sender.Send(jobInfo);

            Console.WriteLine("Job sent.");
        }
        public void Send(JobInfo job)
        {
            Logger.InfoFormat("sending job {0} to {1}", job.JobID, Host);

            Logger.DebugFormat("connecting to {0}", Host);
            var client = new TcpClient();
            client.Connect(Host, Port);
            var stream = client.GetStream();

            var message = new List<byte>();

            int thisJobNumber = IncrementJobCounter();
            var dataFileName = string.Format("dfA{0:D3}{1}", thisJobNumber, job.HostName);
            var controlFileName = string.Format("cfA{0:D3}{1}", thisJobNumber, job.HostName);
            Logger.DebugFormat("LpdSender job number is {0}; control file name is '{1}' and data file name is '{2}'", Host, controlFileName, dataFileName);

            Logger.Debug("initiating the print request");
            message.Add(0x02);
            message.AddRange(Encoding.ASCII.GetBytes(QueueName));
            message.Add(0x0A);
            stream.Write(message.ToArray(), 0, message.Count);
            message.Clear();

            // read ACK
            int b = stream.ReadByte();
            if (b != 0x00)
            {
                Logger.WarnFormat("got 0x{0:X2} after initiating the print request", b);
                throw new BadResponseException("creating a new print job", b);
            }

            Logger.Debug("preparing the control file");
            var controlFile = new StringBuilder();
            controlFile.AppendFormat("H{0}\n", job.HostName);
            controlFile.AppendFormat("P{0}\n", job.UserName);
            controlFile.AppendFormat("J{0}\n", job.DocumentName);
            controlFile.AppendFormat("l{0}\n", dataFileName);
            controlFile.AppendFormat("U{0}\n", dataFileName);
            controlFile.AppendFormat("N{0}\n", job.DocumentName);
            var controlFileBytes = Encoding.Default.GetBytes(controlFile.ToString());

            // send the control file metadata
            Logger.Debug("sending the control file metadata");
            message.Add(0x02);
            message.AddRange(Encoding.ASCII.GetBytes(controlFileBytes.Length.ToString(CultureInfo.InvariantCulture)));
            message.Add(0x20);
            message.AddRange(Encoding.ASCII.GetBytes(controlFileName));
            message.Add(0x0A);
            stream.Write(message.ToArray(), 0, message.Count);
            message.Clear();

            // read ACK
            b = stream.ReadByte();
            if (b != 0x00)
            {
                Logger.WarnFormat("got 0x{0:X2} after sending the control file metadata", b);
                throw new BadResponseException("preparing to send control data", b);
            }

            Logger.Debug("sending the control file data");
            stream.Write(controlFileBytes, 0, controlFileBytes.Length);
            stream.WriteByte(0x00);

            // read ACK
            b = stream.ReadByte();
            if (b != 0x00)
            {
                Logger.WarnFormat("got 0x{0:X2} after sending the control file data", b);
                throw new BadResponseException("sending control data", b);
            }

            Logger.Debug("sending the data file metadata");
            message.Add(0x03);
            message.AddRange(Encoding.ASCII.GetBytes(job.DataFileSize.ToString(CultureInfo.InvariantCulture)));
            message.Add(0x20);
            message.AddRange(Encoding.ASCII.GetBytes(dataFileName));
            message.Add(0x0A);
            stream.Write(message.ToArray(), 0, message.Count);
            message.Clear();

            // read ACK
            b = stream.ReadByte();
            if (b != 0x00)
            {
                Logger.WarnFormat("got 0x{0:X2} after sending the data file metadata", b);
                throw new BadResponseException("preparing to send data", b);
            }

            Logger.Debug("sending the data file data");
            using (var inStream = new FileStream(job.DataFilePath, FileMode.Open, FileAccess.Read))
            {
                Util.CopyStream(inStream, stream, job.DataFileSize);
            }
            stream.WriteByte(0x00);

            // read ACK
            b = stream.ReadByte();
            if (b != 0x00)
            {
                Logger.WarnFormat("got 0x{0:X2} after sending the data file data", b);
                throw new BadResponseException("sending data", b);
            }

            // close
            Logger.Debug("job sent");
            client.Close();
        }
            public JobInfoDrop(JobInfo info)
            {
                Info = info;

                if (info.DataFileSize < 1024L)
                {
                    SizeString = info.DataFileSize + " B";
                }
                else if (info.DataFileSize < 1024L * 1024L)
                {
                    SizeString = (info.DataFileSize / 1024L) + " KB";
                }
                else if (info.DataFileSize < 1024L * 1024L * 1024L)
                {
                    SizeString = (info.DataFileSize / (1024L * 1024L)) + " MB";
                }
                else if (info.DataFileSize < 1024L * 1024L * 1024L * 1024L)
                {
                    SizeString = (info.DataFileSize / (1024L * 1024L * 1024L)) + " GB";
                }
                else
                {
                    SizeString = (info.DataFileSize / (1024L * 1024L * 1024L * 1024L)) + " TB";
                }
            }
        private void HandleJobSubmission(NetworkStream stream)
        {
            var jobFiles = new Dictionary<string, byte[]>();
            var jobFileReferences = new Dictionary<string, string>();
            var jobFileLengths = new Dictionary<string, long>();
            string controlFileName = null;

            // create a new job, reserving a new job ID
            var jobInfo = new JobInfo();

            for (; ; )
            {
                byte[] command;
                try
                {
                    command = ReadUntilLineFeed(stream);
                }
                catch (EndOfStreamException)
                {
                    // it's over!
                    break;
                }

                switch (command[0])
                {
                    case (byte)JobCommandCode.AbortJob:
                    {
                        ReturnSuccess(stream);

                        Logger.Debug("Received: abort current job");

                        // nothing left to do here
                        return;
                    }

                    case (byte)JobCommandCode.ReceiveControlFile:
                    {
                        var controlFileDataString = GetSingleStringArgument(command);
                        var controlFileData = WhiteSpacePattern.Split(controlFileDataString, 2);
                        if (controlFileData.Length != 2)
                        {
                            Logger.WarnFormat("'receive control file' command '{0}' not in format 'length filename'", controlFileDataString);
                            ReturnInvalidSyntax(stream);
                            throw new InvalidDataException("invalid syntax");
                        }

                        var length = int.Parse(controlFileData[0]);
                        controlFileName = controlFileData[1];

                        Logger.DebugFormat("Received: receive {0} bytes of control file named {1}", length, controlFileName);

                        // parse the name
                        var controlFileNameMatch = ControlFileNamePattern.Match(controlFileName);

                        if (!controlFileNameMatch.Success)
                        {
                            Logger.WarnFormat("'receive control file' filename '{0}' has invalid format", controlFileName);
                            ReturnInvalidSyntax(stream);
                            throw new InvalidDataException("control file name doesn't match expected pattern");
                        }

                        // signal that we parsed the command successfully
                        ReturnSuccess(stream);

                        var controlBytes = ReadBytes(length, stream);

                        // store the control file
                        jobFiles[controlFileName] = controlBytes;

                        // read the last byte
                        var b = stream.ReadByte();
                        if (b == 0)
                        {
                            // "thanks!"
                            ReturnSuccess(stream);
                        }
                        else
                        {
                            Logger.Warn("'receive control file' control file contents not succeeded by NUL");
                            ReturnInvalidSyntax(stream);
                            throw new InvalidDataException("control file not succeeded by NUL");
                        }

                        break;
                    }

                    case (byte)JobCommandCode.ReceiveDataFile:
                    {
                        var dataFileDataString = GetSingleStringArgument(command);
                        var dataFileData = WhiteSpacePattern.Split(dataFileDataString, 2);
                        if (dataFileData.Length != 2)
                        {
                            Logger.WarnFormat("'receive data file' command '{0}' not in format 'length filename'", dataFileDataString);
                            ReturnInvalidSyntax(stream);
                            throw new InvalidDataException("invalid syntax");
                        }

                        var length = int.Parse(dataFileData[0]);
                        var lpdDataFileName = dataFileData[1];

                        Logger.DebugFormat("Received: receive {0} bytes of data file named {1}", length, lpdDataFileName);

                        // parse the name
                        var dataFileNameMatch = DataFileNamePattern.Match(lpdDataFileName);

                        if (!dataFileNameMatch.Success)
                        {
                            Logger.WarnFormat("'receive data file' filename '{0}' has invalid format", lpdDataFileName);
                            ReturnInvalidSyntax(stream);
                            throw new InvalidDataException("data file name doesn't match expected pattern");
                        }

                        // must send this so that the client responds
                        ReturnSuccess(stream);

                        var outFileName = Path.Combine(Config.JobDirectory, GetJobDataFilename(jobInfo.JobID, lpdDataFileName));
                        using (var outStream = new FileStream(outFileName, FileMode.CreateNew, FileAccess.Write))
                        {
                            long? copyLength = (length == 0) ? null : (long?)length;

                            long actualLength = Util.CopyStream(stream, outStream, copyLength);

                            jobFileReferences[lpdDataFileName] = outFileName;
                            jobFileLengths[lpdDataFileName] = actualLength;
                        }

                        if (length == 0)
                        {
                            // "thanks!"
                            ReturnSuccess(stream);
                        }
                        else
                        {
                            // read the last byte
                            var b = stream.ReadByte();
                            if (b == 0)
                            {
                                // "thanks!"
                                ReturnSuccess(stream);
                            }
                            else
                            {
                                Logger.Warn("'receive data file' data file contents not succeeded by NUL");
                                ReturnInvalidSyntax(stream);
                                throw new InvalidDataException("data file not succeeded by NUL");
                            }
                        }
                        break;
                    }
                }
            }

            // decode the control file
            string controlString;
            try
            {
                controlString = Utf8Encoding.GetString(jobFiles[controlFileName]);
            }
            catch (DecoderFallbackException)
            {
                controlString = Encoding.Default.GetString(jobFiles[controlFileName]);
            }

            // parse it, with all the magic
            try
            {
                jobInfo = ParseJobInfo(jobInfo, controlString, jobFileReferences, jobFileLengths);
            }
            catch (FormatException)
            {
                ReturnUnsupportedPrintType(stream);
                return;
            }

            OnNewJobReceived(jobInfo);
        }
 protected virtual void OnNewJobReceived(JobInfo job)
 {
     if (NewJobReceived != null)
     {
         NewJobReceived(this, job);
     }
 }
        protected static JobInfo ParseJobInfo(JobInfo jobInfo, string jobInfoString, Dictionary<string, string> dataFilePaths, Dictionary<string, long> dataFileSizes)
        {
            jobInfo.Status = JobInfo.JobStatus.ReadyToPrint;
            jobInfo.TimeOfArrival = DateTimeOffset.UtcNow;

            foreach (var line in jobInfoString.Split('\n'))
            {
                if (line.Length < 2)
                {
                    continue;
                }

                var letter = line[0];
                var param = line.Substring(1);
                switch (letter)
                {
                    case (char)ControlFileCharacters.HostName:
                        jobInfo.HostName = param;
                        break;
                    case (char)ControlFileCharacters.UserIdentification:
                        jobInfo.UserName = param;
                        break;
                    case (char)ControlFileCharacters.JobName:
                        jobInfo.DocumentName = param;
                        break;
                    case (char)ControlFileCharacters.NameOfSourceFile:
                        jobInfo.DocumentName = param;
                        break;
                    case (char)ControlFileCharacters.PrintFileWithControlCharacters:
                        jobInfo.DataFilePath = dataFilePaths[param];
                        jobInfo.DataFileSize = dataFileSizes[param];
                        break;
                    case (char)ControlFileCharacters.UnlinkDataFile:
                        dataFilePaths.Remove(param);
                        dataFileSizes.Remove(param);
                        break;
                    case (char)ControlFileCharacters.PlotCifFile:
                    case (char)ControlFileCharacters.PrintDviFile:
                    case (char)ControlFileCharacters.PrintFormattedFile:
                    case (char)ControlFileCharacters.PlotBerkeleyFile:
                    case (char)ControlFileCharacters.PrintDitroffOutput:
                    case (char)ControlFileCharacters.PrintPostscript:
                    case (char)ControlFileCharacters.PrintFortranCarriageControlFile:
                    case (char)ControlFileCharacters.PrintTroffOutput:
                    case (char)ControlFileCharacters.PrintRasterFile:
                        Logger.WarnFormat("requested printing in unsupported format '{0}'", letter);
                        throw new FormatException("cannot print this format");
                    default:
                        // ignore it...
                        Logger.WarnFormat("ignoring unknown LPD command file command '{0}'", letter);
                        break;
                }
            }

            return jobInfo;
        }
示例#8
0
        private void HandleJobSubmission(NetworkStream stream)
        {
            var    jobFiles          = new Dictionary <string, byte[]>();
            var    jobFileReferences = new Dictionary <string, string>();
            var    jobFileLengths    = new Dictionary <string, long>();
            string controlFileName   = null;

            // create a new job, reserving a new job ID
            var jobInfo = new JobInfo();

            for (; ;)
            {
                byte[] command;
                try
                {
                    command = ReadUntilLineFeed(stream);
                }
                catch (EndOfStreamException)
                {
                    // it's over!
                    break;
                }

                switch (command[0])
                {
                case (byte)JobCommandCode.AbortJob:
                {
                    ReturnSuccess(stream);

                    Logger.Debug("Received: abort current job");

                    // nothing left to do here
                    return;
                }

                case (byte)JobCommandCode.ReceiveControlFile:
                {
                    var controlFileDataString = GetSingleStringArgument(command);
                    var controlFileData       = WhiteSpacePattern.Split(controlFileDataString, 2);
                    if (controlFileData.Length != 2)
                    {
                        Logger.WarnFormat("'receive control file' command '{0}' not in format 'length filename'", controlFileDataString);
                        ReturnInvalidSyntax(stream);
                        throw new InvalidDataException("invalid syntax");
                    }

                    var length = int.Parse(controlFileData[0]);
                    controlFileName = controlFileData[1];

                    Logger.DebugFormat("Received: receive {0} bytes of control file named {1}", length, controlFileName);

                    // parse the name
                    var controlFileNameMatch = ControlFileNamePattern.Match(controlFileName);

                    if (!controlFileNameMatch.Success)
                    {
                        Logger.WarnFormat("'receive control file' filename '{0}' has invalid format", controlFileName);
                        ReturnInvalidSyntax(stream);
                        throw new InvalidDataException("control file name doesn't match expected pattern");
                    }

                    // signal that we parsed the command successfully
                    ReturnSuccess(stream);

                    var controlBytes = ReadBytes(length, stream);

                    // store the control file
                    jobFiles[controlFileName] = controlBytes;

                    // read the last byte
                    var b = stream.ReadByte();
                    if (b == 0)
                    {
                        // "thanks!"
                        ReturnSuccess(stream);
                    }
                    else
                    {
                        Logger.Warn("'receive control file' control file contents not succeeded by NUL");
                        ReturnInvalidSyntax(stream);
                        throw new InvalidDataException("control file not succeeded by NUL");
                    }

                    break;
                }

                case (byte)JobCommandCode.ReceiveDataFile:
                {
                    var dataFileDataString = GetSingleStringArgument(command);
                    var dataFileData       = WhiteSpacePattern.Split(dataFileDataString, 2);
                    if (dataFileData.Length != 2)
                    {
                        Logger.WarnFormat("'receive data file' command '{0}' not in format 'length filename'", dataFileDataString);
                        ReturnInvalidSyntax(stream);
                        throw new InvalidDataException("invalid syntax");
                    }

                    var length          = int.Parse(dataFileData[0]);
                    var lpdDataFileName = dataFileData[1];

                    Logger.DebugFormat("Received: receive {0} bytes of data file named {1}", length, lpdDataFileName);

                    // parse the name
                    var dataFileNameMatch = DataFileNamePattern.Match(lpdDataFileName);

                    if (!dataFileNameMatch.Success)
                    {
                        Logger.WarnFormat("'receive data file' filename '{0}' has invalid format", lpdDataFileName);
                        ReturnInvalidSyntax(stream);
                        throw new InvalidDataException("data file name doesn't match expected pattern");
                    }

                    // must send this so that the client responds
                    ReturnSuccess(stream);

                    var outFileName = Path.Combine(Config.JobDirectory, GetJobDataFilename(jobInfo.JobID, lpdDataFileName));
                    using (var outStream = new FileStream(outFileName, FileMode.CreateNew, FileAccess.Write))
                    {
                        long?copyLength = (length == 0) ? null : (long?)length;

                        long actualLength = Util.CopyStream(stream, outStream, copyLength);

                        jobFileReferences[lpdDataFileName] = outFileName;
                        jobFileLengths[lpdDataFileName]    = actualLength;
                    }

                    if (length == 0)
                    {
                        // "thanks!"
                        ReturnSuccess(stream);
                    }
                    else
                    {
                        // read the last byte
                        var b = stream.ReadByte();
                        if (b == 0)
                        {
                            // "thanks!"
                            ReturnSuccess(stream);
                        }
                        else
                        {
                            Logger.Warn("'receive data file' data file contents not succeeded by NUL");
                            ReturnInvalidSyntax(stream);
                            throw new InvalidDataException("data file not succeeded by NUL");
                        }
                    }
                    break;
                }
                }
            }

            // decode the control file
            string controlString;

            try
            {
                controlString = Utf8Encoding.GetString(jobFiles[controlFileName]);
            }
            catch (DecoderFallbackException)
            {
                controlString = Encoding.Default.GetString(jobFiles[controlFileName]);
            }

            // parse it, with all the magic
            try
            {
                jobInfo = ParseJobInfo(jobInfo, controlString, jobFileReferences, jobFileLengths);
            }
            catch (FormatException)
            {
                ReturnUnsupportedPrintType(stream);
                return;
            }

            OnNewJobReceived(jobInfo);
        }
示例#9
0
        protected static JobInfo ParseJobInfo(JobInfo jobInfo, string jobInfoString, Dictionary <string, string> dataFilePaths, Dictionary <string, long> dataFileSizes)
        {
            jobInfo.Status        = JobInfo.JobStatus.ReadyToPrint;
            jobInfo.TimeOfArrival = DateTimeOffset.UtcNow;

            foreach (var line in jobInfoString.Split('\n'))
            {
                if (line.Length < 2)
                {
                    continue;
                }

                var letter = line[0];
                var param  = line.Substring(1);
                switch (letter)
                {
                case (char)ControlFileCharacters.HostName:
                    jobInfo.HostName = param;
                    break;

                case (char)ControlFileCharacters.UserIdentification:
                    jobInfo.UserName = param;
                    break;

                case (char)ControlFileCharacters.JobName:
                    jobInfo.DocumentName = param;
                    break;

                case (char)ControlFileCharacters.NameOfSourceFile:
                    jobInfo.DocumentName = param;
                    break;

                case (char)ControlFileCharacters.PrintFileWithControlCharacters:
                    jobInfo.DataFilePath = dataFilePaths[param];
                    jobInfo.DataFileSize = dataFileSizes[param];
                    break;

                case (char)ControlFileCharacters.UnlinkDataFile:
                    dataFilePaths.Remove(param);
                    dataFileSizes.Remove(param);
                    break;

                case (char)ControlFileCharacters.PlotCifFile:
                case (char)ControlFileCharacters.PrintDviFile:
                case (char)ControlFileCharacters.PrintFormattedFile:
                case (char)ControlFileCharacters.PlotBerkeleyFile:
                case (char)ControlFileCharacters.PrintDitroffOutput:
                case (char)ControlFileCharacters.PrintPostscript:
                case (char)ControlFileCharacters.PrintFortranCarriageControlFile:
                case (char)ControlFileCharacters.PrintTroffOutput:
                case (char)ControlFileCharacters.PrintRasterFile:
                    Logger.WarnFormat("requested printing in unsupported format '{0}'", letter);
                    throw new FormatException("cannot print this format");

                default:
                    // ignore it...
                    Logger.WarnFormat("ignoring unknown LPD command file command '{0}'", letter);
                    break;
                }
            }

            return(jobInfo);
        }