public void OnFinishedShouldPassDetailsAboutError() { // Arrange var result = default(FinishedEventArgs?); var code = _fixture.Create <int>(); var doc = new Mock <ISettings>().Object; var configuration = new WkHtmlToXConfiguration((int)Environment.OSVersion.Platform, runtimeIdentifier: null) { FinishedAction = eventArgs => { result = eventArgs; }, }; var sut = new PdfProcessor(configuration, _module.Object) { ProcessingDocument = doc, }; // Act sut.OnFinished(new IntPtr(1), code); // Assert using (new AssertionScope()) { result !.Document.Should().Be(doc); result !.Success.Should().Be(code == 1); } }
public void OnProgressChangedShouldPassDetailsAboutError() { // Arrange var progressDescription = _fixture.Create <string>(); _module.Setup(m => m.GetProgressDescription(It.IsAny <IntPtr>())) .Returns(progressDescription); var result = default(ProgressChangedEventArgs?); var doc = new Mock <ISettings>().Object; var configuration = new WkHtmlToXConfiguration((int)Environment.OSVersion.Platform, runtimeIdentifier: null) { ProgressChangedAction = eventArgs => { result = eventArgs; }, }; var sut = new PdfProcessor(configuration, _module.Object) { ProcessingDocument = doc, }; // Act sut.OnProgressChanged(new IntPtr(1)); // Assert using (new AssertionScope()) { result !.Document.Should().Be(doc); result !.Description.Should().Be(progressDescription); } }
static void Main(string[] args) { string inputPath = @"C:\Tao_Folder\About_Work\CES\test\input\"; string filename = @"C:\Tao_Folder\About_Work\CES\test\output\ConcatenatedDocument333.pdf"; if (File.Exists(filename)) { File.Delete(filename); } PdfProcessor.MergeMultiplePDFIntoSinglePDF(filename, inputPath); // ...and start a viewer. Process.Start(filename); //SQL_SP_HelpText helpText = new SQL_SP_HelpText(); ////string connectionString = "Data Source=COSAPXDEV10;SERVER=COSAPXDEV10;User ID=sa;Initial Catalog=$(Catalog);Password=Advent.sa;pooling=yes;Max Pool Size=1110;Connection Lifetime=680;Connect Timeout=660"; //helpText.SP_HelpText("", "", true); //DateMatters(); //TestDoubleFormat(); //Test("(if (any? x) sum (/1 x))"); //Test(":-)"); //Test(@"I said(it's not (yet) complete). (she didn't listen)"); //Test("())("); //Test(null); //Test(""); //Test("(())()"); //Test(@"I said(it's not (yet) complete). (she didn't (listen)"); //Console.ReadLine(); }
public void OnWarningShouldPassDetailsAboutError() { // Arrange var result = default(WarningEventArgs?); var errorMessage = _fixture.Create <string>(); var doc = new Mock <ISettings>().Object; var configuration = new WkHtmlToXConfiguration((int)Environment.OSVersion.Platform, runtimeIdentifier: null) { WarningAction = eventArgs => { result = eventArgs; }, }; var sut = new PdfProcessor(configuration, _module.Object) { ProcessingDocument = doc, }; // Act sut.OnWarning(new IntPtr(1), errorMessage); // Assert using (new AssertionScope()) { result !.Document.Should().Be(doc); result !.Message.Should().Be(errorMessage); } }
public void RegisterEventsShouldRegisterProgressChangedCallbackWhenSpecified() { // Arrange _module.Setup(m => m.SetProgressChangedCallback(It.IsAny <IntPtr>(), It.IsAny <VoidCallback>())); var configuration = new WkHtmlToXConfiguration((int)Environment.OSVersion.Platform, runtimeIdentifier: null) { ProgressChangedAction = _ => { }, }; var sut = new PdfProcessor(configuration, _module.Object); // Act sut.RegisterEvents(new IntPtr(12)); // Assert using (new AssertionScope()) { _module.Verify( m => m.SetProgressChangedCallback( It.IsAny <IntPtr>(), It.IsAny <VoidCallback>()), Times.Once); } }
public PdfProcessorTest() { _fixture = new Fixture(); _module = new Mock <IWkHtmlToPdfModule>(); _sut = new PdfProcessor( new WkHtmlToXConfiguration((int)Environment.OSVersion.Platform, null), _module.Object); }
public void Signing_ExpiredLicense_ThrowsException() { TestHelper.Job.Profile.OutputFormat = OutputFormat.Pdf; TestHelper.Job.Profile.PdfSettings.Signature.CertificateFile = TestHelper.GenerateTestFile(TestFile.CertificationFile_ExpiredP12); var ex = Assert.Throws <ProcessingException>(() => PdfProcessor.ProcessPdf(TestHelper.Job)); Assert.AreEqual(ErrorCode.Signature_Invalid, ex.ErrorCode, "Wrong error code for expired certificate/signature"); }
protected override void OnMessage(WebSocketSharp.MessageEventArgs e) { // Basically just echo whatever's sent here JObject json = JObject.Parse(e.Data); string serverRequest = (string)json["BackendRequest"]; if (string.IsNullOrEmpty(serverRequest)) { Console.WriteLine(" - echoing a message to all sessions"); // Not a server request, so just echo the contents to everybody Sessions.Broadcast(e.Data); } Console.WriteLine(" - handling a socket message:" + serverRequest); switch (serverRequest) { case "UpdateQueueCounts": //Sessions.Broadcast(Program.GetQueueInfoJson()); break; case "AddBitcoinAddress": BackendLoop.AddBitcoinAddress((string)json["Address"]); break; case "Metapackage": BackendLoop.ProcessMetapackage(SocketMessage.FromXml((string)json["XmlData"])); break; case "ConvertPdfHires": try { JObject newJson = new JObject(); newJson["MessageType"] = "EchoBackend"; newJson["DocumentId"] = json["DocumentId"]; Sessions.Broadcast(newJson.ToString()); PdfProcessor.Rerasterize(Document.FromIdentity(Int32.Parse((string)json["DocumentId"])), PdfProcessor.PdfProcessorOptions.HighQuality | PdfProcessor.PdfProcessorOptions.ForceOrphans); } catch (Exception exc) { JObject newJson = new JObject(); newJson["MessageType"] = "Exception"; newJson["ExceptionString"] = exc.ToString(); Sessions.Broadcast(newJson.ToString()); } // Convert with high quality -- done on backend with lower priority than the immediate frontend conversion break; default: // do nothing; break; } }
public ActionResult Index() { using (var reader = new PdfReader(@"S:\git\PdfEditor\form12a.pdf")) { var processor = new PdfProcessor(); var html = processor.ConvertToHtml(reader, 1); //return View(html); return(Content(html)); } }
public void TestUpdatePDF() { Application application = new Application(); application.FirstName = "John"; application.LastName = "Johnson"; String inputPath = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + "\\Docs\\BLGLegal Intake Form AcroForm.pdf"; String outputPath = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + "\\Docs\\BLGLegal Intake Form_new.pdf"; PdfProcessor pdfproc = new PdfProcessor(); pdfproc.UpdatePDF(outputPath, inputPath, application); }
public void CheckActions_ResultedFileContainsOnlyImages_ProperlyRotated() { string inPdfPath = Directory.GetCurrentDirectory() + @"\BlackRectangles1.pdf"; PdfProcessorTests.FlushResourceToFile(Resources + "BlackRectangles.pdf", inPdfPath); string outPdfPath = inPdfPath + ".out.pdf"; using (var reader = new PdfReader(inPdfPath)) { using (var fs = new FileStream(outPdfPath, FileMode.Create)) { using (var stamper = new PdfStamper(reader, fs)) { using (var render = new GsNetPdfRender(inPdfPath, 150)) { var andFilter = new AndFilter( new HasSpecialCsResourceFilter(reader), new NotFilter(new HasFontResourceFilter(reader)), new NotFilter( new PageHasSpecificKeyFilter( reader, RenderPageAction.EstPageRendered, new PdfBoolean(true)))); using (var action = new RenderPageAction(reader, stamper, andFilter, render)) { var processor = new PdfProcessor(new List <IPdfAction> { action }); for (int i = 1; i <= reader.NumberOfPages; i++) { processor.Execute(i); } } } } } } using (var reader = new PdfReader(outPdfPath)) { AssertPageRotation(reader, 1, 0); AssertOnlyImageAndImageSize(reader, 1, 1275, 1650); AssertPageRotation(reader, 2, 90); AssertOnlyImageAndImageSize(reader, 2, 1275, 1650); AssertPageRotation(reader, 3, 180); AssertOnlyImageAndImageSize(reader, 3, 1275, 1650); } }
public void ShouldThrowExceptionWhenNullPassedInModuleConstructor() { // Arrange // ReSharper disable once AssignmentIsFullyDiscarded #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. #pragma warning disable IDISP004 // Don't ignore created IDisposable. Action action = () => _ = new PdfProcessor( new WkHtmlToXConfiguration((int)Environment.OSVersion.Platform, null), null); #pragma warning restore IDISP004 // Don't ignore created IDisposable. #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Act & Assert action.Should().Throw <ArgumentNullException>(); }
private static void LongRun(object orderObject) { RasterizeDocumentHiresOrder order = null; try { order = (RasterizeDocumentHiresOrder)orderObject; Document document = Document.FromIdentity(order.DocumentId); PdfProcessor.Rerasterize((Document)document, PdfProcessor.PdfProcessorOptions.HighQuality | PdfProcessor.PdfProcessorOptions.ForceOrphans); order.Close(); } catch (Exception exception) { order?.ThrewException(exception); } if (order != null) { order.HasTerminated = true; } }
private static void Main(string[] args) { // Are we running yet? if (!SystemSettings.DatabaseInitialized) { // will restart the service every 15s until db initialized on OOBE // also, the read of DatabaseInitialized can and will fail if // we're not initalized enough to even have a database throw new InvalidOperationException(); } // Checking for schemata upgrade first of all, after seeing that db exists int startupDbVersion = Database.SwarmDb.DbVersion; DatabaseMaintenance.UpgradeSchemata(); testMode = false; SystemSettings.BackendHostname = Dns.GetHostName(); // Other one-time initializations FinancialTransactions.FixAllUnsequenced(); SupportFunctions.OperatingTopology = OperatingTopology.Backend; // Begin main loop UnixSignal[] killSignals = null; if (!Debugger.IsAttached) { killSignals = new UnixSignal[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM) }; } BotLog.Write(0, "MainCycle", string.Empty); BotLog.Write(0, "MainCycle", "-----------------------------------------------"); BotLog.Write(0, "MainCycle", string.Empty); if (args.Length > 0) { if (args[0].ToLower() == "test") { /* * BotLog.Write(0, "MainCycle", "Running self-tests"); * HeartBeater.Instance.Beat(heartbeatFile); // Otherwise Heartbeater.Beat() will fail in various places * * testMode = true; * Console.WriteLine("Testing All Maintenance Processes (except membership-changing ones)."); * PWLog.Write(PWLogItem.None, 0, PWLogAction.SystemTest, string.Empty, string.Empty); * * Console.WriteLine("\r\n10-second intervals:"); * OnEveryTenSeconds(); * Console.WriteLine("\r\nEvery minute:"); * OnEveryMinute(); * Console.WriteLine("\r\nEvery five minutes:"); * OnEveryFiveMinutes(); * Console.WriteLine("\r\nEvery hour:"); * OnEveryHour(); * Console.WriteLine("\r\nNoon:"); * OnNoon(); * Console.WriteLine("\r\nMidnight:"); * OnMidnight(); */ Console.WriteLine("Testing database access..."); Console.WriteLine(SwarmDb.GetDatabaseForReading().GetPerson(1).Name); Console.WriteLine(SwarmDb.GetDatabaseForReading().GetPerson(1).PasswordHash); Console.WriteLine("Creating OutboundComm..."); OutboundComm.CreateNotification(null, NotificationResource.System_Startup_Backend); Console.WriteLine("Transmitting..."); OutboundComms comms = OutboundComms.GetOpen(); Console.WriteLine("{0} open items in outbound comms.", comms.Count); foreach (OutboundComm comm in comms) { if (comm.TransmitterClass != "Swarmops.Utility.Communications.CommsTransmitterMail") { throw new NotImplementedException(); } ICommsTransmitter transmitter = new CommsTransmitterMail(); OutboundCommRecipients recipients = comm.Recipients; PayloadEnvelope envelope = PayloadEnvelope.FromXml(comm.PayloadXml); foreach (OutboundCommRecipient recipient in recipients) { transmitter.Transmit(envelope, recipient.Person); } } Console.Write("\r\nAll tests run. Waiting for mail queue to flush... "); while (!MailTransmitter.CanExit) { Thread.Sleep(50); } Console.WriteLine("done."); BotLog.Write(0, "MainCycle", "Exiting self-tests"); return; } if (args[0].ToLower() == "console") { Console.WriteLine("\r\nRunning Swarmops-Backend in CONSOLE mode.\r\n"); // ------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------- // ----------------------- INSERT ANY ONE-OFF ACTIONS HERE ------------------------- Console.Write("\r\nWaiting for mail queue to flush... "); while (!MailTransmitter.CanExit) { Thread.Sleep(50); } Console.WriteLine("done."); return; } if (args[0].ToLowerInvariant() == "pdfregen") { if (args.Length > 1) { int docId = Int32.Parse(args[1]); PdfProcessor.Rerasterize(Document.FromIdentity(docId)); } else { Console.WriteLine("Regenerating all bitmaps from PDF uploads."); PdfProcessor.RerasterizeAll(); Console.WriteLine("Done."); } return; } if (args[0].ToLower() == "rsm") { Console.WriteLine("Testing character encoding: räksmörgås RÄKSMÖRGÅS"); return; } } /* * MailMessage message = new MailMessage(); * message.From = new MailAddress(Strings.MailSenderAddress, Strings.MailSenderName); * message.To.Add (new MailAddress ("*****@*****.**", "Rick Falkvinge (Piratpartiet)")); * message.Subject = "Räksmörgåsarnas ékÖNÖMÏåvdëlnïng"; * message.Body = "Hejsan hoppsan Räksmörgåsar."; * message.BodyEncoding = Encoding.Default; * message.SubjectEncoding = Encoding.Default; * * SmtpClient smtpClient = new SmtpClient ("localhost"); * smtpClient.Credentials = null; // mono bug * smtpClient.Send (message);*/ Console.WriteLine(" * Swarmops Backend starting"); BotLog.Write(0, "MainCycle", "Backend STARTING"); // Disable certificate checking due to Mono not installing with a certificate repository - this is UTTERLY broken SupportFunctions.DisableSslCertificateChecks(); // MONO BUG/MISFEATURE: Mono has no root certificates, so can't verify cert // Tell sysop we're starting OutboundComm.CreateNotification(null, NotificationResource.System_Startup_Backend); // Check for existence of installation ID. If not, create one. Warning: has privacy implications when communicated. if (Persistence.Key["SwarmopsInstallationId"] == string.Empty) { Persistence.Key["SwarmopsInstallationId"] = Guid.NewGuid().ToString(); } // Check for existence of bitcoin hotwallet root BitcoinUtility.VerifyBitcoinHotWallet(); // Initialize backend socket server int backendSocketPort = SystemSettings.WebsocketPortBackend; _socketServer = new WebSocketServer(backendSocketPort); _socketServer.AddWebSocketService <BackendServices>("/Backend"); _socketServer.Start(); // Initialize socket client to Blockchain.Info (pending our own services) using ( _blockChainInfoSocket = new WebSocket("wss://ws.blockchain.info/inv?api_code=" + SystemSettings.BlockchainSwarmopsApiKey)) { // Begin maintenance loop DateTime cycleStartTime = DateTime.UtcNow; DateTime cycleEndTime; int lastSecond = cycleStartTime.Second; int lastMinute = cycleStartTime.Minute; int lastHour = cycleStartTime.Hour; bool exitFlag = false; _blockChainInfoSocket.OnOpen += new EventHandler(OnBlockchainOpen); _blockChainInfoSocket.OnError += new EventHandler <ErrorEventArgs>(OnBlockchainError); _blockChainInfoSocket.OnClose += new EventHandler <CloseEventArgs>(OnBlockchainClose); _blockChainInfoSocket.OnMessage += new EventHandler <MessageEventArgs>(OnBlockchainMessage); _blockChainInfoSocket.Connect(); while (!exitFlag) // exit is handled by signals handling at end of loop { BotLog.Write(0, "MainCycle", "Cycle Start"); cycleStartTime = DateTime.UtcNow; cycleEndTime = cycleStartTime.AddSeconds(10); try { OnEveryTenSeconds(); if (cycleStartTime.Second < lastSecond) { OnEveryMinute(); if (cycleStartTime.Minute % 5 == 0) { OnEveryFiveMinutes(); } } if (cycleStartTime.Minute < lastMinute) { OnEveryHour(); if (DateTime.Now.Hour == 10 && DateTime.Today.DayOfWeek == DayOfWeek.Tuesday) { OnTuesdayMorning(); } if (DateTime.Now.Hour == 7 && DateTime.Today.DayOfWeek == DayOfWeek.Monday) { OnMondayMorning(); } } if (cycleStartTime.Hour >= 12 && lastHour < 12) { OnNoon(); } if (cycleStartTime.Hour < lastHour) { OnMidnight(); } } catch (Exception e) { // Note each "OnEvery..." catches its own errors and sends Exception mails, // so that failure in one should not stop the others from running. This particular // code should never run. ExceptionMail.Send(new Exception("Failed in swarmops-backend main loop", e), true); } lastSecond = cycleStartTime.Second; lastMinute = cycleStartTime.Minute; lastHour = cycleStartTime.Hour; // Wait for a maximum of ten seconds (the difference between cycleStartTime and cycleEndTime) int iterationCount = 0; DateTime utcNow = DateTime.UtcNow; while (utcNow < cycleEndTime && !exitFlag) { int signalIndex = 250; // Handle important service orders (those that can't be lost in a random loss // of connection of a socket): BackendServiceOrders backendOrders = BackendServiceOrders.GetNextBatch(5); backendOrders.Execute(); // takes at most 250ms per BSO reqs // Block until a SIGINT or SIGTERM signal is generated, or 1/4 second has passed. // However, we can't do that in a development environment - it won't have the // Mono.Posix assembly, and won't understand UnixSignals. So people running this in // a dev environment will need to stop it manually. if (!Debugger.IsAttached) { signalIndex = UnixSignal.WaitAny(killSignals, 250); } else { TimeSpan timeLeft = (cycleEndTime - utcNow); BotLog.Write(0, "MainCycle Debug", string.Format(CultureInfo.InvariantCulture, "Waiting for {0:F2} more seconds for cycle end", timeLeft.TotalMilliseconds / 1000.0)); Thread.Sleep(250); } if (signalIndex < 250) { exitFlag = true; Console.WriteLine("Caught signal " + killSignals[signalIndex].Signum + ", exiting"); BotLog.Write(0, "MainCycle", "EXIT SIGNAL (" + killSignals[signalIndex].Signum + "), terminating backend"); } utcNow = DateTime.UtcNow; // Every second, send an internal heartbeat if (iterationCount++ % 4 == 0) { InternalHeartbeat(); } } } } Console.WriteLine(" * Swarmops Backend stopping"); BotLog.Write(0, "MainCycle", "BACKEND EXITING, sending backend-termination notices"); /* * if (HeartBeater.Instance.WasKilled) * { * // removed unconditional delete, cron job that restarts bot uses it to know that it is intentionally down. * ExceptionMail.Send(new Exception("HeartBeater triggered restart of Swarmops Backend. Will commence after 800 seconds."), false); * }*/ BotLog.Write(0, "MainCycle", "...done"); /* * while (!MailTransmitter.CanExit) * { * System.Threading.Thread.Sleep(50); * }*/ _socketServer.Stop(); Thread.Sleep(2000); }
private static void ProcessExpensifyUploadThread(object args) { string guidProgress = ((ProcessThreadArguments)args).GuidProgress; string guidFiles = ((ProcessThreadArguments)args).GuidFiles; Person currentUser = ((ProcessThreadArguments)args).CurrentUser; Organization organization = ((ProcessThreadArguments)args).Organization; ProgressBarBackend progress = new ProgressBarBackend(guidProgress); try { Documents documents = Documents.RecentFromDescription(guidFiles); progress.Set(2); // indicate more life if (documents.Count != 1) { return; // abort } Document uploadedDoc = documents[0]; // TODO: ATTEMPT TO DETERMINE CURRENCY FROM FILE, USING ORIGINAL CURRENCY + ORIGINAL AMOUNT string csvEntire; using (StreamReader reader = uploadedDoc.GetReader(1252)) { csvEntire = reader.ReadToEnd(); } GuidCache.Set("ExpensifyRaw-" + guidFiles, csvEntire); string[] csvLines = csvEntire.Split(new char[] { '\r', '\n' }); string[] fieldNames = csvLines[0].Split(','); // Map fields to column indexes Dictionary <ExpensifyColumns, int> fieldMap = new Dictionary <ExpensifyColumns, int>(); for (int loop = 0; loop < fieldNames.Length; loop++) { switch (fieldNames[loop].ToLowerInvariant().Trim('\"')) { case "timestamp": fieldMap[ExpensifyColumns.Timestamp] = loop; break; case "amount": fieldMap[ExpensifyColumns.AmountFloat] = loop; break; case "merchant": fieldMap[ExpensifyColumns.Merchant] = loop; break; case "comment": fieldMap[ExpensifyColumns.Comment] = loop; break; case "category": fieldMap[ExpensifyColumns.CategoryCustom] = loop; break; case "mcc": fieldMap[ExpensifyColumns.CategoryStandard] = loop; break; case "vat": fieldMap[ExpensifyColumns.VatFloat] = loop; break; case "original currency": fieldMap[ExpensifyColumns.OriginalCurrency] = loop; break; case "original amount": fieldMap[ExpensifyColumns.OriginalCurrencyAmountFloat] = loop; break; case "receipt": fieldMap[ExpensifyColumns.ReceiptUrl] = loop; break; default: // ignore any unknown fields break; } } ExpensifyColumns[] requiredData = { ExpensifyColumns.AmountFloat, ExpensifyColumns.CategoryCustom, ExpensifyColumns.CategoryStandard, ExpensifyColumns.Comment, ExpensifyColumns.Merchant, ExpensifyColumns.OriginalCurrency, ExpensifyColumns.OriginalCurrencyAmountFloat, ExpensifyColumns.ReceiptUrl, ExpensifyColumns.Timestamp }; foreach (ExpensifyColumns requiredColumn in requiredData) { if (!fieldMap.ContainsKey(requiredColumn)) { // Abort as invalid file GuidCache.Set("Results-" + guidFiles, new AjaxCallExpensifyUploadResult { Success = false, ErrorType = "ERR_INVALIDCSV", DisplayMessage = Resources.Pages.Financial.FileExpenseClaim_Expensify_Error_InvalidCsv }); progress.Set(100); // terminate progress bar, causes retrieval of result documents[0].Delete(); // prevents further processing return; // terminates thread } } // TODO: Much more general-case error conditions if not all fields are filled bool vatEnabled = organization.VatEnabled; if (vatEnabled && !fieldMap.ContainsKey(ExpensifyColumns.VatFloat)) { // Error: Organization needs a VAT field GuidCache.Set("Results-" + guidFiles, new AjaxCallExpensifyUploadResult { Success = false, ErrorType = "ERR_NEEDSVAT", DisplayMessage = Resources.Pages.Financial.FileExpenseClaim_Expensify_Error_NeedsVat }); progress.Set(100); // terminate progress bar, causes retrieval of result documents[0].Delete(); // prevents further processing return; // terminates thread } List <ExpensifyRecord> recordList = new List <ExpensifyRecord>(); CsvHelper.Configuration.Configuration config = new CsvHelper.Configuration.Configuration(); config.HasHeaderRecord = true; using (TextReader textReader = new StringReader(csvEntire)) { CsvReader csvReader = new CsvReader(textReader, config); csvReader.Read(); // bypass header record -- why isn't this done automatically? while (csvReader.Read()) { ExpensifyRecord newRecord = new ExpensifyRecord(); Int64 amountExpensifyCents = newRecord.AmountCents = Formatting.ParseDoubleStringAsCents( csvReader.GetField(fieldMap[ExpensifyColumns.AmountFloat]), CultureInfo.InvariantCulture); newRecord.OriginalCurrency = Currency.FromCode(csvReader.GetField(fieldMap[ExpensifyColumns.OriginalCurrency])); newRecord.OriginalAmountCents = Formatting.ParseDoubleStringAsCents( csvReader.GetField(fieldMap[ExpensifyColumns.OriginalCurrencyAmountFloat]), CultureInfo.InvariantCulture); newRecord.Timestamp = DateTime.Parse(csvReader.GetField(fieldMap[ExpensifyColumns.Timestamp])); bool amountNeedsTranslation = false; if (newRecord.OriginalCurrency.Identity != organization.Currency.Identity) { amountNeedsTranslation = true; // May or may not be the same as Expensify calculated newRecord.AmountCents = new Money(newRecord.OriginalAmountCents, newRecord.OriginalCurrency, newRecord.Timestamp) .ToCurrency(organization.Currency).Cents; } newRecord.Description = csvReader.GetField(fieldMap[ExpensifyColumns.Merchant]); string comment = csvReader.GetField(fieldMap[ExpensifyColumns.Comment]).Trim(); if (!string.IsNullOrEmpty(comment)) { newRecord.Description += " / " + comment; } newRecord.CategoryCustom = csvReader.GetField(fieldMap[ExpensifyColumns.CategoryCustom]); newRecord.CategoryStandard = csvReader.GetField(fieldMap[ExpensifyColumns.CategoryStandard]); newRecord.ReceiptUrl = csvReader.GetField(fieldMap[ExpensifyColumns.ReceiptUrl]); newRecord.Guid = Guid.NewGuid().ToString(); if (vatEnabled) { Int64 vatOriginalCents = Formatting.ParseDoubleStringAsCents( csvReader.GetField(fieldMap[ExpensifyColumns.VatFloat]), CultureInfo.InvariantCulture); if (amountNeedsTranslation) { double vatRatio = vatOriginalCents / (double)amountExpensifyCents; newRecord.VatCents = (Int64)(newRecord.AmountCents * vatRatio); } else { newRecord.VatCents = vatOriginalCents; } } recordList.Add(newRecord); } } progress.Set(10); // We now need to get all the receipt images. This is a little tricky as we don't have the URL // of the receipt directly, we only have the URL of a webpage that contains JavaScript code // to fetch the receipt image. // Get relative date part string relativePath = Document.DailyStorageFolder.Substring(Document.StorageRoot.Length); // Get all receipts for (int loop = 0; loop < recordList.Count; loop++) { progress.Set(loop * 90 / recordList.Count + 10); using (WebClient client = new WebClient()) { string receiptResource = client.DownloadString(recordList[loop].ReceiptUrl); // We now have the web page which holds information about where the actual receipt is located. Regex regex = new Regex(@"\s*var transaction\s*=\s*(?<jsonTxInfo>{.*});", RegexOptions.Multiline); Match match = regex.Match(receiptResource); if (match.Success) { string txInfoString = match.Groups["jsonTxInfo"].ToString(); JObject txInfo = JObject.Parse(txInfoString); recordList[loop].ExtendedInfo = txInfoString; string expensifyFileName = (string)txInfo["receiptFilename"]; string actualReceiptUrl = "https://s3.amazonaws.com/receipts.expensify.com/" + expensifyFileName; string newGuidString = recordList[loop].Guid; string fullyQualifiedFileName = Document.DailyStorageFolder + newGuidString; string relativeFileName = relativePath + newGuidString; client.DownloadFile(actualReceiptUrl, fullyQualifiedFileName); recordList[loop].ReceiptFileNameHere = newGuidString; // If original file name ends in PDF, initiate conversion. if (expensifyFileName.ToLowerInvariant().EndsWith(".pdf")) { // Convert low resolution Documents docs = new PdfProcessor().RasterizeOne(fullyQualifiedFileName, recordList[loop].Description, newGuidString, currentUser, organization); recordList[loop].Documents = docs; // Ask backend for high-res conversion RasterizeDocumentHiresOrder backendOrder = new RasterizeDocumentHiresOrder(docs[0]); backendOrder.Create(); } else { Document doc = Document.Create(relativePath + newGuidString, expensifyFileName, 0, newGuidString, null, currentUser); recordList[loop].Documents = Documents.FromSingle(doc); } } } } // We now have the individual expenses and all accompanying receipts. // Create the expense claim group, then the individual expense records, // and assign the Documents to the records and the records to the Group, // so the user can review all of it. // TODO: Suggest initial budgets List <ExpensifyOutputRecord> outputRecords = new List <ExpensifyOutputRecord>(); string docString = "<a href='/Pages/v5/Support/StreamUpload.aspx?DocId={0}&hq=1' data-caption=\"{1}\" class='FancyBox_Gallery' data-fancybox='{2}'>"; string documentsAll = String.Empty; foreach (ExpensifyRecord record in recordList) { foreach (Document document in record.Documents) { documentsAll += String.Format(docString, document.Identity, document.ClientFileName.Replace("\"", "'"), "D" + record.Documents[0].Identity.ToString(CultureInfo.InvariantCulture)); } } AjaxCallExpensifyUploadResult result = new AjaxCallExpensifyUploadResult { Success = true, Data = FormatExpensifyOutputRecords(recordList), Footer = FormatExpensifyFooter(recordList), Documents = documentsAll }; GuidCache.Set("Results-" + guidFiles, result); GuidCache.Set("ExpensifyData-" + guidFiles, recordList); } catch (Exception exception) { // Abort as exception GuidCache.Set("Results-" + guidFiles, new AjaxCallExpensifyUploadResult { Success = false, ErrorType = "ERR_EXCEPTION", DisplayMessage = exception.ToString() }); } finally { progress.Set(100); // terminate progress bar, causes retrieval of result } }
protected override void OnMessage(WebSocketSharp.MessageEventArgs e) { // Basically just echo whatever's sent here Console.WriteLine(" - a client says " + e.Data); JObject json = JObject.Parse(e.Data); string serverRequest = (string)json["ServerRequest"]; if (string.IsNullOrEmpty(serverRequest)) { // Not a server request, so just echo the contents to everybody Sessions.Broadcast(e.Data); } switch (serverRequest) { case "AddBitcoinAddress": FrontendLoop.AddBitcoinAddress((string)json["Address"]); break; case "Metapackage": ProcessMetapackage((string)json["XmlData"]); break; case "Ping": // TODO: Request heartbeat from backend // Sessions.Broadcast("{\"messageType\":\"Heartbeat\"}"); break; case "ConvertPdf": try { JArray pdfFilesArray = (JArray)json["PdfFiles"]; JArray pdfClientNamesArray = (JArray)json["ClientFileNames"]; List <RasterizationTarget> rasterizationTargets = new List <RasterizationTarget>(); for (int loop = 0; loop < pdfFilesArray.Count; loop++) { rasterizationTargets.Add(new RasterizationTarget { FullyQualifiedFileName = Document.StorageRoot + (string)pdfFilesArray[loop], ClientFileName = (string)pdfClientNamesArray[loop] }); } PdfProcessor pdfMaker = new PdfProcessor(); pdfMaker.RasterizationProgress += BroadcastGuidProgress; pdfMaker.RasterizeMany(rasterizationTargets.ToArray(), (string)json["Guid"], _authority.Person, _authority.Organization); } catch (Exception exc) { Sessions.Broadcast("{\"messageType\":\"Debug\",\"data\":\"Exception - " + exc.GetType() + " - " + exc.ToString().Replace("\"", "\\\"") + "\"}"); } break; case "ConvertPdfHires": // Send to backend JObject backendRequest = new JObject(); backendRequest["BackendRequest"] = "ConvertPdfHires"; backendRequest["DocumentId"] = json["DocumentId"]; FrontendLoop.SendMessageUpstream(backendRequest); break; default: // do nothing; break; } }