diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72de34f --- /dev/null +++ b/.gitignore @@ -0,0 +1,388 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Nuget personal access tokens and Credentials +nuget.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +.idea/ +*.sln.iml \ No newline at end of file diff --git a/Common/AdobeIcon.ico b/Common/AdobeIcon.ico new file mode 100644 index 0000000..9ceebfa Binary files /dev/null and b/Common/AdobeIcon.ico differ diff --git a/Common/Adobe_CreatePDF_icon.png b/Common/Adobe_CreatePDF_icon.png new file mode 100644 index 0000000..bb310db Binary files /dev/null and b/Common/Adobe_CreatePDF_icon.png differ diff --git a/Common/SipgateFaxdruckerSharedAssemblyInfo.cs b/Common/SipgateFaxdruckerSharedAssemblyInfo.cs new file mode 100644 index 0000000..1085856 --- /dev/null +++ b/Common/SipgateFaxdruckerSharedAssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyCompany("sipgate GmbH")] +[assembly: AssemblyProduct("sipgate Faxdrucker")] +[assembly: AssemblyCopyright("Copyright © sipgate GmbH 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +#if DEBUG +[assembly: AssemblyConfiguration("DEBUG")] +#else +[assembly: AssemblyConfiguration("RELEASE")] +#endif \ No newline at end of file diff --git a/Common/WixUIBannerBmp.bmp b/Common/WixUIBannerBmp.bmp new file mode 100644 index 0000000..188473b Binary files /dev/null and b/Common/WixUIBannerBmp.bmp differ diff --git a/Common/WixUIDialogBmp.bmp b/Common/WixUIDialogBmp.bmp new file mode 100644 index 0000000..9be7231 Binary files /dev/null and b/Common/WixUIDialogBmp.bmp differ diff --git a/Common/agpl-3.0.rtf b/Common/agpl-3.0.rtf new file mode 100644 index 0000000..031bbbb --- /dev/null +++ b/Common/agpl-3.0.rtf @@ -0,0 +1,389 @@ +{\rtf1\ansi\ansicpg1252\cocoartf2513 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\froman\fcharset0 Times-Roman;\f1\fswiss\fcharset0 Helvetica;\f2\froman\fcharset0 Times-Bold; +\f3\froman\fcharset0 Times-BoldItalic;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\vieww34880\viewh20980\viewkind0 +\deftab709 +\pard\pardeftab709\partightenfactor0 + +\f0\fs24 \cf0 sipgate Faxdrucker - Copyright 2021 - sipgate GmbH\ +\pard\pardeftab709\sb240\sa120\partightenfactor0 +\cf0 sipgate Faxdrucker links to Ghostscript, which is licensed under AGPL v3, so it is obliged to be licensed under the same terms. By using this software, you agree that you have received notice of the terms imposed by the AGPL v3 license. +\f1 \expnd0\expndtw0\kerning0 +\ + +\f2\b\fs28 GNU AFFERO GENERAL PUBLIC LICENSE +\f1\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 Version 3, 19 November 2007\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +Copyright (C) 2007 Free Software Foundation, Inc. {\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt https://fsf.org/}}\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f2\b\fs28 \cf0 \expnd0\expndtw0\kerning0 +Preamble +\f1\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The precise terms and conditions for copying, distribution and modification follow.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f2\b\fs28 \cf0 \expnd0\expndtw0\kerning0 +TERMS AND CONDITIONS +\f1\b0\fs24 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 0. Definitions. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 "This License" refers to version 3 of the GNU Affero General Public License.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +A "covered work" means either the unmodified Program or a work based on the Program.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +1. Source Code. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The Corresponding Source for a work in source code form is that same work.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +2. Basic Permissions. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +4. Conveying Verbatim Copies. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +5. Conveying Modified Source Versions. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:\kerning1\expnd0\expndtw0 \ +\pard\tx720\pardeftab709\li720\fi-360\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +a) The work must carry prominent notices stating that you modified it, and giving a relevant date.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices".\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +6. Conveying Non-Source Forms. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:\kerning1\expnd0\expndtw0 \ +\pard\tx720\pardeftab709\li720\fi-360\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +7. Additional Terms. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:\kerning1\expnd0\expndtw0 \ +\pard\tx720\pardeftab709\li720\fi-360\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +d) Limiting the use for publicity purposes of names of licensors or authors of the material; or\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +8. Termination. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +9. Acceptance Not Required for Having Copies. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +10. Automatic Licensing of Downstream Recipients. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +11. Patents. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version".\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +12. No Surrender of Others' Freedom. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +13. Remote Network Interaction; Use with the GNU General Public License. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +14. Revised Versions of this License. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +15. Disclaimer of Warranty. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +16. Limitation of Liability. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f3\i\b\fs23 \cf0 \expnd0\expndtw0\kerning0 +17. Interpretation of Sections 15 and 16. +\f1\i0\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 + +\f2\b \cf0 \expnd0\expndtw0\kerning0 +END OF TERMS AND CONDITIONS +\f0\b0 \kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\qc\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab709\sb240\sa120\partightenfactor0 + +\f2\b\fs28 \cf0 How to Apply These Terms to Your New Programs +\f1\b0\fs24 \ +\pard\pardeftab709\partightenfactor0 + +\f0 \cf0 If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 \expnd0\expndtw0\kerning0 +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.\kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\li720\partightenfactor0 + +\fs18 \cf0 \expnd0\expndtw0\kerning0 + +\fs24 \kerning1\expnd0\expndtw0 \ + +\fs18 \expnd0\expndtw0\kerning0 +Copyright (C) +\fs24 \kerning1\expnd0\expndtw0 \ + +\fs18 \expnd0\expndtw0\kerning0 +\ +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +\fs24 \kerning1\expnd0\expndtw0 \ + +\fs18 \expnd0\expndtw0\kerning0 +\ +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +\fs24 \kerning1\expnd0\expndtw0 \ + +\fs18 \expnd0\expndtw0\kerning0 +\ +You should have received a copy of the GNU Affero General Public License along with this program. If not, see {\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt https://www.gnu.org/licenses/}}. +\fs24 \kerning1\expnd0\expndtw0 \ +\pard\pardeftab709\partightenfactor0 + +\fs20 \cf0 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab709\partightenfactor0 + +\fs24 \cf0 Also add information on how to contact you by electronic and paper mail.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +\ +\pard\pardeftab709\sb86\sa86\partightenfactor0 +\cf0 If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements.\kerning1\expnd0\expndtw0 \ +\expnd0\expndtw0\kerning0 +You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see {\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt https://www.gnu.org/licenses/}}.\kerning1\expnd0\expndtw0 \ +} \ No newline at end of file diff --git a/Common/gear.png b/Common/gear.png new file mode 100644 index 0000000..658a581 Binary files /dev/null and b/Common/gear.png differ diff --git a/Common/gear2.png b/Common/gear2.png new file mode 100644 index 0000000..4379a61 Binary files /dev/null and b/Common/gear2.png differ diff --git a/Common/gear3.png b/Common/gear3.png new file mode 100644 index 0000000..cab6737 Binary files /dev/null and b/Common/gear3.png differ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..fa4acc8 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,245 @@ +sipgate Faxdrucker - Copyright 2021 - sipgate GmbH + +sipgate Faxdrucker links to Ghostscript, which is licensed under AGPL v3, so it is obliged to be licensed under the same terms. By using this software, you agree that you have received notice of the terms imposed by the AGPL v3 license. + +**GNU AFFERO GENERAL PUBLIC LICENSE** + +Version 3, 19 November 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +**Preamble** + +The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. + +A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. + +The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. + +An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. + +The precise terms and conditions for copying, distribution and modification follow. + +**TERMS AND CONDITIONS** + +***0. Definitions.*** + +"This License" refers to version 3 of the GNU Affero General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based on the Program. + +To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + +***1. Source Code.*** + +The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. + +A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +***2. Basic Permissions.*** + +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +***3. Protecting Users' Legal Rights From Anti-Circumvention Law.*** + +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + +***4. Conveying Verbatim Copies.*** + +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + +***5. Conveying Modified Source Versions.*** + +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + +a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + +b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". + +c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + +d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + +***6. Conveying Non-Source Forms.*** + +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + +a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + +b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + +c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + +d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + +e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + +***7. Additional Terms.*** + +"Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + +b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + +c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + +d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + +e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + +f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + +***8. Termination.*** + +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + +***9. Acceptance Not Required for Having Copies.*** + +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + +***10. Automatic Licensing of Downstream Recipients.*** + +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + +***11. Patents.*** + +A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + +***12. No Surrender of Others' Freedom.*** + +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + +***13. Remote Network Interaction; Use with the GNU General Public License.*** + +Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. + +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. + +***14. Revised Versions of this License.*** + +The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + +***15. Disclaimer of Warranty.*** + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +***16. Limitation of Liability.*** + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +***17. Interpretation of Sections 15 and 16.*** + +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +**END OF TERMS AND CONDITIONS** + +**How to Apply These Terms to Your New Programs** + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + + +Copyright (C) + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . diff --git a/Lib/PS5UI.DLL b/Lib/PS5UI.DLL new file mode 100644 index 0000000..a62c801 Binary files /dev/null and b/Lib/PS5UI.DLL differ diff --git a/Lib/PSCRIPT.HLP b/Lib/PSCRIPT.HLP new file mode 100644 index 0000000..34ee8ba Binary files /dev/null and b/Lib/PSCRIPT.HLP differ diff --git a/Lib/PSCRIPT.NTF b/Lib/PSCRIPT.NTF new file mode 100644 index 0000000..b46cbf5 Binary files /dev/null and b/Lib/PSCRIPT.NTF differ diff --git a/Lib/PSCRIPT5.DLL b/Lib/PSCRIPT5.DLL new file mode 100644 index 0000000..334cf27 Binary files /dev/null and b/Lib/PSCRIPT5.DLL differ diff --git a/Lib/SCPDFPRN.ppd b/Lib/SCPDFPRN.ppd new file mode 100644 index 0000000..265bd26 --- /dev/null +++ b/Lib/SCPDFPRN.ppd @@ -0,0 +1,521 @@ +*PPD-Adobe: "4.3" +*FileVersion: "1.1" +*FormatVersion: "4.3" +*LanguageEncoding: ISOLatin1 +*LanguageVersion: English +*Manufacturer: "Ghostscript" +*ModelName: "Ghostscript PDF Writer" +*ShortNickName: "Ghostscript" +*NickName: "Ghostscript" +*% PCFileName should be of the form XXNNNNNN.PPD where XX is an assigned +*% manufacturer code. +*PCFileName: "SCPDFPRN.PPD" +*Product: "(PDF Scribe)" +*PSVersion: "(3010) 815" + +*% *DefaultImageableArea: +*% *DefaultPageRegion: +*% *PageRegion: +*% *ImageableArea: +*% *DefaultPageSize: +*% *PageSize: +*% *DefaultPaperDimension: +*% *PaperDimension: + +*% == Above are required + +*% This file was adapted from GHOSTPDF.PPD for PDF Scribe + +*Copyright: "2004-2006 Ghostgum Software Pty Ltd" +*% +*% Copyright (C) 2004-2006, Ghostgum Software Pty Ltd. All rights reserved. +*% +*% Permission is hereby granted, free of charge, to any person obtaining +*% a copy of this file ("Software"), to deal in the Software without +*% restriction, including without limitation the rights to use, copy, +*% modify, merge, publish, distribute, sublicense, and/or sell copies of +*% this Software, and to permit persons to whom this file is furnished to +*% do so, subject to the following conditions: +*% +*% This Software is distributed with NO WARRANTY OF ANY KIND. No author +*% or distributor accepts any responsibility for the consequences of using it, +*% or for whether it serves any particular purpose or works at all, unless he +*% or she says so in writing. +*% +*% The above copyright notice and this permission notice shall be included +*% in all copies or substantial portions of the Software. + +*% There is an accompanying file ghostpdf.inf that is used to +*% install this PPD on Windows 2k/XP. +*% This PPD includes configuration items specific to generating +*% PDF files with ghostscript. +*% If you are not using the ghostscript pdfwrite device, +*% all items in the PDF group should be left as "Default". + + +*% == Basic Capabilities +*LanguageLevel: "3" +*ColorDevice: True +*DefaultColorSpace: RGB +*FileSystem: True +*Extensions: CMYK FileSystem Composite +*TTRasterizer: Type42 +*FreeVM: "10000000" +*PrintPSErrors: True +*ContoneOnly: True +*% AccurateScreensSupport: True + +*% order dependency +*% 10 HWResolution +*% 20 PageSize and other page device parameters +*% 30 PDFSETTINGS +*% 40 distiller parameters + +*% == Resolution +*OpenUI *Resolution: PickOne +*DefaultResolution: 600dpi +*OrderDependency: 10 AnySetup *Resolution +*Resolution 72dpi: "<< /HWResolution [72 72] >> setpagedevice" +*Resolution 96dpi: "<< /HWResolution [96 96] >> setpagedevice" +*Resolution 144dpi: "<< /HWResolution [144 144] >> setpagedevice" +*Resolution 150dpi: "<< /HWResolution [150 150] >> setpagedevice" +*Resolution 300dpi: "<< /HWResolution [300 300] >> setpagedevice" +*Resolution 600dpi: "<< /HWResolution [600 600] >> setpagedevice" +*Resolution 720dpi: "<< /HWResolution [720 720] >> setpagedevice" +*Resolution 1200dpi: "<< /HWResolution [1200 1200] >> setpagedevice" +*Resolution 2400dpi: "<< /HWResolution [2400 2400] >> setpagedevice" +*Resolution 3600dpi: "<< /HWResolution [3600 3600] >> setpagedevice" +*Resolution 4000dpi: "<< /HWResolution [4000 4000] >> setpagedevice" +*CloseUI: *Resolution + + +*% == Paper stuff +*% Page sizes taken from ghostscript gs_statd.ps. +*% Ghostscript pdfwrite ignores Orientation, so set the +*% custom page width/height and then use an Install procedure +*% to rotate the image. + +*HWMargins: 0 0 0 0 +*ParamCustomPageSize Width: 1 points 1 5670 +*ParamCustomPageSize Height: 2 points 1 5670 +*ParamCustomPageSize WidthOffset/Width Margin: 3 points 0 5670 +*ParamCustomPageSize HeightOffset/Height Margin: 4 points 0 5670 +*ParamCustomPageSize Orientation: 5 int 0 3 +*NonUIOrderDependency: 20 AnySetup *CustomPageSize +*CustomPageSize True: " + 5 -2 roll exch 5 2 roll + 3 -2 roll exch 3 2 roll + [ {} + {90 rotate 0 currentpagedevice /PageSize get 0 get neg translate} + {180 rotate currentpagedevice /PageSize get + dup 0 get neg exch 1 get neg translate} + {270 rotate currentpagedevice /PageSize get 1 get neg 0 translate} + ] exch get + 4 dict dup begin 6 1 roll + /Install exch def + 2 array astore /PageOffset exch def + 2 array astore /PageSize exch def + /ImagingBBox null def + end setpagedevice" +*End +*MaxMediaWidth: "5670" +*MaxMediaHeight: "5670" + +*LandscapeOrientation: Any + +*OpenUI *PageSize: PickOne +*DefaultPageSize: Letter +*OrderDependency: 20 AnySetup *PageSize +*PageSize Tabloid: "<< /PageSize [792 1224] /ImagingBBox null >> setpagedevice" +*PageSize Ledger: "<< /PageSize [1224 792] /ImagingBBox null >> setpagedevice" +*PageSize Legal: "<< /PageSize [612 1008] /ImagingBBox null >> setpagedevice" +*PageSize Letter: "<< /PageSize [612 792] /ImagingBBox null >> setpagedevice" +*PageSize LetterSmall: "<< /PageSize [612 792] /ImagingBBox [25 25 587 767] >> setpagedevice" +*PageSize Statement: "<< /PageSize [396 612] /ImagingBBox null >> setpagedevice" +*PageSize Note: "<< /PageSize [612 792] /ImagingBBox [25 25 587 767] >> setpagedevice" +*PageSize A0: "<< /PageSize [2384 3370] /ImagingBBox null >> setpagedevice" +*PageSize A1: "<< /PageSize [1684 2384] /ImagingBBox null >> setpagedevice" +*PageSize A2: "<< /PageSize [1191 1684] /ImagingBBox null >> setpagedevice" +*PageSize A3: "<< /PageSize [842 1191] /ImagingBBox null >> setpagedevice" +*PageSize A4: "<< /PageSize [595 842] /ImagingBBox null >> setpagedevice" +*PageSize A4Small: "<< /PageSize [595 842] /ImagingBBox [25 25 570 817] >> setpagedevice" +*PageSize A5: "<< /PageSize [420 595] /ImagingBBox null >> setpagedevice" +*PageSize A6: "<< /PageSize [297 420] /ImagingBBox null >> setpagedevice" +*PageSize A7: "<< /PageSize [210 297] /ImagingBBox null >> setpagedevice" +*PageSize A8: "<< /PageSize [148 210] /ImagingBBox null >> setpagedevice" +*PageSize A9: "<< /PageSize [105 148] /ImagingBBox null >> setpagedevice" +*PageSize A10: "<< /PageSize [73 105] /ImagingBBox null >> setpagedevice" +*PageSize ISOB0/ISO B0: "<< /PageSize [2835 4008] /ImagingBBox null >> setpagedevice" +*PageSize ISOB1/ISO B1: "<< /PageSize [2004 2835] /ImagingBBox null >> setpagedevice" +*PageSize ISOB2/ISO B2: "<< /PageSize [1417 2004] /ImagingBBox null >> setpagedevice" +*PageSize ISOB3/ISO B3: "<< /PageSize [1001 1417] /ImagingBBox null >> setpagedevice" +*PageSize ISOB4/ISO B4: "<< /PageSize [709 1001] /ImagingBBox null >> setpagedevice" +*PageSize ISOB5/ISO B5: "<< /PageSize [499 709] /ImagingBBox null >> setpagedevice" +*PageSize ISOB6/ISO B6: "<< /PageSize [354 499] /ImagingBBox null >> setpagedevice" +*PageSize B0/JIS B0: "<< /PageSize [2920 4127] /ImagingBBox null >> setpagedevice" +*PageSize B1/JIS B1: "<< /PageSize [2064 2920] /ImagingBBox null >> setpagedevice" +*PageSize B2/JIS B2: "<< /PageSize [1460 2064] /ImagingBBox null >> setpagedevice" +*PageSize B3/JIS B3: "<< /PageSize [1032 1460] /ImagingBBox null >> setpagedevice" +*PageSize B4/JIS B4: "<< /PageSize [729 1032] /ImagingBBox null >> setpagedevice" +*PageSize B5/JIS B5: "<< /PageSize [516 729] /ImagingBBox null >> setpagedevice" +*PageSize B6/JIS B6: "<< /PageSize [363 516] /ImagingBBox null >> setpagedevice" +*PageSize EnvC0/Envelope C0: "<< /PageSize [2599 3677] /ImagingBBox null >> setpagedevice" +*PageSize EnvC1/Envelope C1: "<< /PageSize [1837 2599] /ImagingBBox null >> setpagedevice" +*PageSize EnvC2/Envelope C2: "<< /PageSize [1296 1837] /ImagingBBox null >> setpagedevice" +*PageSize EnvC3/Envelope C3: "<< /PageSize [918 1296] /ImagingBBox null >> setpagedevice" +*PageSize EnvC4/Envelope C4: "<< /PageSize [649 918] /ImagingBBox null >> setpagedevice" +*PageSize EnvC5/Envelope C5: "<< /PageSize [459 649] /ImagingBBox null >> setpagedevice" +*PageSize EnvC6/Envelope C6: "<< /PageSize [323 459] /ImagingBBox null >> setpagedevice" +*PageSize ARCHE: "<< /PageSize [2592 3456] /ImagingBBox null >> setpagedevice" +*PageSize ARCHD: "<< /PageSize [1728 2592] /ImagingBBox null >> setpagedevice" +*PageSize ARCHC: "<< /PageSize [1296 1728] /ImagingBBox null >> setpagedevice" +*PageSize ARCHB: "<< /PageSize [864 1296] /ImagingBBox null >> setpagedevice" +*PageSize ARCHA: "<< /PageSize [648 864] /ImagingBBox null >> setpagedevice" +*PageSize FLSA: "<< /PageSize [612 936] /ImagingBBox null >> setpagedevice" +*PageSize FLSE: "<< /PageSize [612 936] /ImagingBBox null >> setpagedevice" +*PageSize PA4: "<< /PageSize [595 792] /ImagingBBox null >> setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*DefaultPageRegion: Letter +*OrderDependency: 20 AnySetup *PageRegion +*PageRegion Tabloid: "<< /PageSize [792 1224] /ImagingBBox null >> setpagedevice" +*PageRegion Ledger: "<< /PageSize [1224 792] /ImagingBBox null >> setpagedevice" +*PageRegion Legal: "<< /PageSize [612 1008] /ImagingBBox null >> setpagedevice" +*PageRegion Letter: "<< /PageSize [612 792] /ImagingBBox null >> setpagedevice" +*PageRegion LetterSmall: "<< /PageSize [612 792] /ImagingBBox [25 25 587 767] >> setpagedevice" +*PageRegion Note: "<< /PageSize [612 792] /ImagingBBox [25 25 587 767] >> setpagedevice" +*PageRegion Statement: "<< /PageSize [396 612] /ImagingBBox null >> setpagedevice" +*PageRegion A0: "<< /PageSize [2384 3370] /ImagingBBox null >> setpagedevice" +*PageRegion A1: "<< /PageSize [1684 2384] /ImagingBBox null >> setpagedevice" +*PageRegion A2: "<< /PageSize [1191 1684] /ImagingBBox null >> setpagedevice" +*PageRegion A3: "<< /PageSize [842 1191] /ImagingBBox null >> setpagedevice" +*PageRegion A4: "<< /PageSize [595 842] /ImagingBBox null >> setpagedevice" +*PageRegion A4Small: "<< /PageSize [595 842] /ImagingBBox [25 25 570 817] >> setpagedevice" +*PageRegion A5: "<< /PageSize [420 595] /ImagingBBox null >> setpagedevice" +*PageRegion A6: "<< /PageSize [297 420] /ImagingBBox null >> setpagedevice" +*PageRegion A7: "<< /PageSize [210 297] /ImagingBBox null >> setpagedevice" +*PageRegion A8: "<< /PageSize [148 210] /ImagingBBox null >> setpagedevice" +*PageRegion A9: "<< /PageSize [105 148] /ImagingBBox null >> setpagedevice" +*PageRegion A10: "<< /PageSize [73 105] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB0/ISO B0: "<< /PageSize [2835 4008] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB1/ISO B1: "<< /PageSize [2004 2835] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB2/ISO B2: "<< /PageSize [1417 2004] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB3/ISO B3: "<< /PageSize [1001 1417] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB4/ISO B4: "<< /PageSize [709 1001] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB5/ISO B5: "<< /PageSize [499 709] /ImagingBBox null >> setpagedevice" +*PageRegion ISOB6/ISO B6: "<< /PageSize [354 499] /ImagingBBox null >> setpagedevice" +*PageRegion B0/JIS B0: "<< /PageSize [2920 4127] /ImagingBBox null >> setpagedevice" +*PageRegion B1/JIS B1: "<< /PageSize [2064 2920] /ImagingBBox null >> setpagedevice" +*PageRegion B2/JIS B2: "<< /PageSize [1460 2064] /ImagingBBox null >> setpagedevice" +*PageRegion B3/JIS B3: "<< /PageSize [1032 1460] /ImagingBBox null >> setpagedevice" +*PageRegion B4/JIS B4: "<< /PageSize [729 1032] /ImagingBBox null >> setpagedevice" +*PageRegion B5/JIS B5: "<< /PageSize [516 729] /ImagingBBox null >> setpagedevice" +*PageRegion B6/JIS B6: "<< /PageSize [363 516] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC0/Envelope C0: "<< /PageSize [2599 3677] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC1/Envelope C1: "<< /PageSize [1837 2599] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC2/Envelope C2: "<< /PageSize [1296 1837] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC3/Envelope C3: "<< /PageSize [918 1296] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC4/Envelope C4: "<< /PageSize [649 918] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC5/Envelope C5: "<< /PageSize [459 649] /ImagingBBox null >> setpagedevice" +*PageRegion EnvC6/Envelope C6: "<< /PageSize [323 459] /ImagingBBox null >> setpagedevice" +*PageRegion ARCHE: "<< /PageSize [2592 3456] /ImagingBBox null >> setpagedevice" +*PageRegion ARCHD: "<< /PageSize [1728 2592] /ImagingBBox null >> setpagedevice" +*PageRegion ARCHC: "<< /PageSize [1296 1728] /ImagingBBox null >> setpagedevice" +*PageRegion ARCHB: "<< /PageSize [864 1296] /ImagingBBox null >> setpagedevice" +*PageRegion ARCHA: "<< /PageSize [648 864] /ImagingBBox null >> setpagedevice" +*PageRegion FLSA: "<< /PageSize [612 936] /ImagingBBox null >> setpagedevice" +*PageRegion FLSE: "<< /PageSize [612 936] /ImagingBBox null >> setpagedevice" +*PageRegion PA4: "<< /PageSize [595 792] /ImagingBBox null >> setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Tabloid: "0 0 792 1224" +*ImageableArea Ledger: "0 0 1224 792" +*ImageableArea Legal: "0 0 612 1008" +*ImageableArea Letter: "0 0 612 792" +*ImageableArea LetterSmall: "25 25 587 767" +*ImageableArea Note: "25 25 587 767" +*ImageableArea Statement: "0 0 396 612" +*ImageableArea A0: "0 0 2384 3370" +*ImageableArea A1: "0 0 1684 2384" +*ImageableArea A2: "0 0 1191 1684" +*ImageableArea A3: "0 0 842 1191" +*ImageableArea A4: "0 0 595 842" +*ImageableArea A4Small: "25 25 570 817" +*ImageableArea A5: "0 0 420 595" +*ImageableArea A6: "0 0 297 420" +*ImageableArea A7: "0 0 210 297" +*ImageableArea A8: "0 0 148 210" +*ImageableArea A9: "0 0 105 148" +*ImageableArea A10: "0 0 73 105" +*ImageableArea ISOB0/ISO B0: "0 0 2835 4008" +*ImageableArea ISOB1/ISO B1: "0 0 2004 2835" +*ImageableArea ISOB2/ISO B2: "0 0 1417 2004" +*ImageableArea ISOB3/ISO B3: "0 0 1001 1417" +*ImageableArea ISOB4/ISO B4: "0 0 709 1001" +*ImageableArea ISOB5/ISO B5: "0 0 499 709" +*ImageableArea ISOB6/ISO B6: "0 0 354 499" +*ImageableArea B0/JIS B0: "0 0 2920 4127" +*ImageableArea B1/JIS B1: "0 0 2064 2920" +*ImageableArea B2/JIS B2: "0 0 1460 2064" +*ImageableArea B3/JIS B3: "0 0 1032 1460" +*ImageableArea B4/JIS B4: "0 0 729 1032" +*ImageableArea B5/JIS B5: "0 0 516 729" +*ImageableArea B6/JIS B6: "0 0 363 516" +*ImageableArea EnvC0/Envelope C0: "0 0 2599 3677" +*ImageableArea EnvC1/Envelope C1: "0 0 1837 2599" +*ImageableArea EnvC2/Envelope C2: "0 0 1296 1837" +*ImageableArea EnvC3/Envelope C3: "0 0 918 1296" +*ImageableArea EnvC4/Envelope C4: "0 0 649 918" +*ImageableArea EnvC5/Envelope C5: "0 0 459 649" +*ImageableArea EnvC6/Envelope C6: "0 0 323 459" +*ImageableArea ARCHE: "0 0 2592 3456" +*ImageableArea ARCHD: "0 0 1728 2592" +*ImageableArea ARCHC: "0 0 1296 1728" +*ImageableArea ARCHB: "0 0 864 1296" +*ImageableArea ARCHA: "0 0 648 864" +*ImageableArea FLSA: "0 0 612 936" +*ImageableArea FLSE: "0 0 612 936" +*ImageableArea PA4: "0 0 595 792" + +*DefaultPaperDimension: Letter +*PaperDimension Tabloid: "792 1224" +*PaperDimension Ledger: "1224 792" +*PaperDimension Legal: "612 1008" +*PaperDimension Letter: "612 792" +*PaperDimension LetterSmall: "612 792" +*PaperDimension Note: "612 792" +*PaperDimension Statement: "396 612" +*PaperDimension A0: "2384 3370" +*PaperDimension A1: "1684 2384" +*PaperDimension A2: "1191 1684" +*PaperDimension A3: "842 1191" +*PaperDimension A4: "595 842" +*PaperDimension A4Small: "595 842" +*PaperDimension A5: "420 595" +*PaperDimension A6: "297 420" +*PaperDimension A7: "210 297" +*PaperDimension A8: "148 210" +*PaperDimension A9: "105 148" +*PaperDimension A10: "73 105" +*PaperDimension ISOB0/ISO B0: "2835 4008" +*PaperDimension ISOB1/ISO B1: "2004 2835" +*PaperDimension ISOB2/ISO B2: "1417 2004" +*PaperDimension ISOB3/ISO B3: "1001 1417" +*PaperDimension ISOB4/ISO B4: "709 1001" +*PaperDimension ISOB5/ISO B5: "499 709" +*PaperDimension ISOB6/ISO B6: "354 499" +*PaperDimension B0/JIS B0: "2920 4127" +*PaperDimension B1/JIS B1: "2064 2920" +*PaperDimension B2/JIS B2: "1460 2064" +*PaperDimension B3/JIS B3: "1032 1460" +*PaperDimension B4/JIS B4: "729 1032" +*PaperDimension B5/JIS B5: "516 729" +*PaperDimension B6/JIS B6: "363 516" +*PaperDimension EnvC0/Envelope C0: "2599 3677" +*PaperDimension EnvC1/Envelope C1: "1837 2599" +*PaperDimension EnvC2/Envelope C2: "1296 1837" +*PaperDimension EnvC3/Envelope C3: "918 1296" +*PaperDimension EnvC4/Envelope C4: "649 918" +*PaperDimension EnvC5/Envelope C5: "459 649" +*PaperDimension EnvC6/Envelope C6: "323 459" +*PaperDimension ARCHE: "2592 3456" +*PaperDimension ARCHD: "1728 2592" +*PaperDimension ARCHC: "1296 1728" +*PaperDimension ARCHB: "864 1296" +*PaperDimension ARCHA: "648 864" +*PaperDimension FLSA: "612 936" +*PaperDimension FLSE: "612 936" +*PaperDimension PA4: "595 792" + + +*% == Fonts +*DefaultFont: Courier +*% First the standard 35 aliases with the actual fonts commented out. +*Font Bookman-Demi: Standard "(1.05)" Standard ROM +*% *Font URWBookmanL-DemiBold: Standard "(1.05)" Standard ROM +*Font Bookman-DemiItalic: Standard "(1.05)" Standard ROM +*% *Font URWBookmanL-DemiBoldItal: Standard "(1.05)" Standard ROM +*Font Bookman-Light: Standard "(1.05)" Standard ROM +*% *Font URWBookmanL-Ligh: Standard "(1.05)" Standard ROM +*Font Bookman-LightItalic: Standard "(1.05)" Standard ROM +*% *Font URWBookmanL-LighItal: Standard "(1.05)" Standard ROM +*Font Courier: Standard "(1.05)" Standard ROM +*% *Font NimbusMonL-Regu: Standard "(1.05)" Standard ROM +*Font Courier-Oblique: Standard "(1.05)" Standard ROM +*% *Font NimbusMonL-ReguObli: Standard "(1.05)" Standard ROM +*Font Courier-Bold: Standard "(1.05)" Standard ROM +*% *Font NimbusMonL-Bold: Standard "(1.05)" Standard ROM +*Font Courier-BoldOblique: Standard "(1.05)" Standard ROM +*% *Font NimbusMonL-BoldObli: Standard "(1.05)" Standard ROM +*Font AvantGarde-Book: Standard "(1.05)" Standard ROM +*% *Font URWGothicL-Book: Standard "(1.05)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(1.05)" Standard ROM +*% *Font URWGothicL-BookObli: Standard "(1.05)" Standard ROM +*Font AvantGarde-Demi: Standard "(1.05)" Standard ROM +*% *Font URWGothicL-Demi: Standard "(1.05)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(1.05)" Standard ROM +*% *Font URWGothicL-DemiObli: Standard "(1.05)" Standard ROM +*Font Helvetica: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-Regu: Standard "(1.05)" Standard ROM +*Font Helvetica-Oblique: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-ReguItal: Standard "(1.05)" Standard ROM +*Font Helvetica-Bold: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-Bold: Standard "(1.05)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-BoldItal: Standard "(1.05)" Standard ROM +*Font Helvetica-Narrow: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-ReguCond: Standard "(1.05)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-ReguCondItal: Standard "(1.05)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-BoldCond: Standard "(1.05)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(1.05)" Standard ROM +*% *Font NimbusSanL-BoldCondItal: Standard "(1.05)" Standard ROM +*Font Palatino-Roman: Standard "(1.05)" Standard ROM +*% *Font URWPalladioL-Roma: Standard "(1.05)" Standard ROM +*Font Palatino-Italic: Standard "(1.05)" Standard ROM +*% *Font URWPalladioL-Ital: Standard "(1.05)" Standard ROM +*Font Palatino-Bold: Standard "(1.05)" Standard ROM +*% *Font URWPalladioL-Bold: Standard "(1.05)" Standard ROM +*Font Palatino-BoldItalic: Standard "(1.05)" Standard ROM +*% *Font URWPalladioL-BoldItal: Standard "(1.05)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(1.05)" Standard ROM +*% *Font CenturySchL-Roma: Standard "(1.05)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(1.05)" Standard ROM +*% *Font CenturySchL-Ital: Standard "(1.05)" Standard ROM +*Font NewCenturySchlbk-Bold: Standard "(1.05)" Standard ROM +*% *Font CenturySchL-Bold: Standard "(1.05)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(1.05)" Standard ROM +*% *Font CenturySchL-BoldItal: Standard "(1.05)" Standard ROM +*Font Times-Roman: Standard "(1.05)" Standard ROM +*% *Font NimbusRomNo9L-Regu: Standard "(1.05)" Standard ROM +*Font Times-Italic: Standard "(1.05)" Standard ROM +*% *Font NimbusRomNo9L-ReguItal: Standard "(1.05)" Standard ROM +*Font Times-Bold: Standard "(1.05)" Standard ROM +*% *Font NimbusRomNo9L-Medi: Standard "(1.05)" Standard ROM +*Font Times-BoldItalic: Standard "(1.05)" Standard ROM +*% *Font NimbusRomNo9L-MediItal: Standard "(1.05)" Standard ROM +*Font Symbol: Special "(001.005)" Special ROM +*% *Font StandardSymL: Special (001.005)" Special ROM +*Font ZapfChancery-MediumItalic: Standard "(1.05)" Standard ROM +*% *Font URWChanceryL-MediItal: Standard "(1.05)" Standard ROM +*Font ZapfDingbats: Special (001.005)" Special ROM +*% *Font Dingbats: Special (001.005)" Special ROM +*% Then a few ghostscript extras +*Font Charter-Roman: Standard "(2.0-1.0)" Standard ROM +*Font CharterBT-Roman: Standard "(2.0-1.0)" Standard ROM +*Font Charter-Italic: Standard "(2.0-1.0)" Standard ROM +*Font CharterBT-Italic: Standard "(2.0-1.0)" Standard ROM +*Font Charter-Bold: Standard "(2.0-1.0)" Standard ROM +*Font CharterBT-Bold: Standard "(2.0-1.0)" Standard ROM +*Font Charter-BoldItalic: Standard "(2.0-1.0)" Standard ROM +*Font CharterBT-BoldItalic: Standard "(2.0-1.0)" Standard ROM +*Font Utopia-Regular: Standard "(001.001)" Standard ROM +*Font Utopia-Italic: Standard "(001.001)" Standard ROM +*Font Utopia-Bold: Standard "(001.001)" Standard ROM +*Font Utopia-BoldItalic: Standard "(001.001)" Standard ROM + +*% == Most of these set distiller parameters +*% If the target device is not the Ghostscript pdfwrite device, +*% then these should all be left at "Default" +*OpenGroup: PDF + +*% == The pdfwrite device can select different color spaces +*OpenUI *ColorModel/PDF color Model: PickOne +*DefaultColorModel: Default +*OrderDependency: 20 AnySetup *ColorModel +*ColorModel Default: "" +*ColorModel Grey: "<< /ProcessColorModel /DeviceGray >> setpagedevice" +*ColorModel RGB: "<< /ProcessColorModel /DeviceRGB >> setpagedevice" +*ColorModel CMYK: "<< /ProcessColorModel /DeviceCMYK >> setpagedevice" +*CloseUI: *ColorModel + +*OpenUI *PDFSettings/PDF Settings: PickOne +*DefaultPDFSettings: Default +*OrderDependency: 30 AnySetup *PDFSettings +*PDFSettings Default: "" +*PDFSettings Screen: ".distillersettings /screen get setdistillerparams" +*PDFSettings Ebook: ".distillersettings /ebook get setdistillerparams" +*PDFSettings Printer: ".distillersettings /printer get setdistillerparams" +*PDFSettings Prepress: ".distillersettings /prepress get setdistillerparams" +*CloseUI: *PDFSettings + +*OpenUI *ColorImageFilter/PDF color Image Compression: PickOne +*DefaultColorImageFilter: Default +*OrderDependency: 40 AnySetup *ColorImageFilter +*ColorImageFilter Default: "" +*ColorImageFilter JPEG: "<< /AutoFilterColorImages false /ColorImageFilter /DCTEncode >> setdistillerparams" +*ColorImageFilter Flate: "<< /AutoFilterColorImages false /ColorImageFilter /FlateEncode >> setdistillerparams" +*CloseUI: *ColorImageFilter + +*OpenUI *GrayImageFilter/PDF Grey Image Compression: PickOne +*DefaultGrayImageFilter: Default +*OrderDependency: 40 AnySetup *GrayImageFilter +*GrayImageFilter Default: "" +*GrayImageFilter JPEG: "<< /AutoFilterGrayImages false /GrayImageFilter /DCTEncode >> setdistillerparams" +*GrayImageFilter Flate: "<< /AutoFilterGrayImages false /GrayImageFilter /FlateEncode >> setdistillerparams" +*CloseUI: *GrayImageFilter + +*OpenUI *MonoImageFilter/PDF Monochrome Image Compression: PickOne +*DefaultMonoImageFilter: Default +*OrderDependency: 40 AnySetup *MonoImageFilter +*MonoImageFilter Default: "" +*MonoImageFilter FaxG3/Fax G3: "<< /AutoFilterMonoImages false /MonoImageFilter /CCITTFaxEncode >> setdistillerparams" +*MonoImageFilter Flate: "<< /AutoFilterMonoImages false /MonoImageFilter /FlateEncode >> setdistillerparams" +*CloseUI: *MonoImageFilter + +*OpenUI *CompatibilityLevel/PDF Compatibility: PickOne +*DefaultCompatibilityLevel: Default +*OrderDependency: 40 AnySetup *CompatibilityLevel +*CompatibilityLevel Default: "" +*CompatibilityLevel 1.2: "<< /CompatibilityLevel 1.2 >> setdistillerparams" +*CompatibilityLevel 1.3: "<< /CompatibilityLevel 1.3 >> setdistillerparams" +*CompatibilityLevel 1.4: "<< /CompatibilityLevel 1.4 >> setdistillerparams" +*CloseUI: *CompatibilityLevel + +*OpenUI *AutoRotatePages/PDF AutoRotatePages: PickOne +*DefaultAutoRotatePages: Default +*OrderDependency: 40 AnySetup *AutoRotatePages +*AutoRotatePages Default: "" +*AutoRotatePages None: "<< /AutoRotatePages /None >> setdistillerparams" +*AutoRotatePages PageByPage: "<< /AutoRotatePages /PageByPage >> setdistillerparams" +*AutoRotatePages All: "<< /AutoRotatePages /All >> setdistillerparams" +*CloseUI: *AutoRotatePages + +*OpenUI *ParseDSCComments/PDF ParseDSCComments: PickOne +*DefaultParseDSCComments: Default +*OrderDependency: 40 AnySetup *ParseDSCComments +*ParseDSCComments Default: "" +*ParseDSCComments True: "<< /ParseDSCComments true >> setdistillerparams" +*ParseDSCComments False: "<< /ParseDSCComments false >> setdistillerparams" +*CloseUI: *ParseDSCComments + +*OpenUI *EmbedAllFonts/PDF EmbedAllFonts: PickOne +*DefaultEmbedAllFonts: Default +*OrderDependency: 40 AnySetup *EmbedAllFonts +*EmbedAllFonts Default: "" +*EmbedAllFonts True: "<< /EmbedAllFonts true >> setdistillerparams" +*EmbedAllFonts False: "<< /EmbedAllFonts false >> setdistillerparams" +*CloseUI: *EmbedAllFonts + +*OpenUI *SubsetFonts/PDF SubsetFonts: PickOne +*DefaultSubsetFonts: Default +*OrderDependency: 40 AnySetup *SubsetFonts +*SubsetFonts Default: "" +*SubsetFonts True: "<< /SubsetFonts true >> setdistillerparams" +*SubsetFonts False: "<< /SubsetFonts false >> setdistillerparams" +*CloseUI: *SubsetFonts + +*OpenUI *CompressPages/PDF Compress Pages: PickOne +*DefaultCompressPages: Default +*OrderDependency: 40 AnySetup *CompressPages +*CompressPages Default: "" +*CompressPages True: "<< /CompressPages true >> setdistillerparams" +*CompressPages False: "<< /CompressPages false >> setdistillerparams" +*CloseUI: *CompressPages + +*CloseGroup: PDF + +*% End of Ghostscript PDF Writer PPD file diff --git a/Lib/WixNetFxExtension.dll b/Lib/WixNetFxExtension.dll new file mode 100644 index 0000000..c82d7ad Binary files /dev/null and b/Lib/WixNetFxExtension.dll differ diff --git a/Lib/WixUIExtension.dll b/Lib/WixUIExtension.dll new file mode 100644 index 0000000..3ef5de5 Binary files /dev/null and b/Lib/WixUIExtension.dll differ diff --git a/Lib/gsdll32.dll b/Lib/gsdll32.dll new file mode 100644 index 0000000..ea1dcc7 Binary files /dev/null and b/Lib/gsdll32.dll differ diff --git a/Lib/gsdll64.dll b/Lib/gsdll64.dll new file mode 100644 index 0000000..6872589 Binary files /dev/null and b/Lib/gsdll64.dll differ diff --git a/Lib/redmon32pdfscribe.dll b/Lib/redmon32pdfscribe.dll new file mode 100644 index 0000000..7e4af63 Binary files /dev/null and b/Lib/redmon32pdfscribe.dll differ diff --git a/Lib/redmon64pdfscribe.dll b/Lib/redmon64pdfscribe.dll new file mode 100644 index 0000000..b1e27b4 Binary files /dev/null and b/Lib/redmon64pdfscribe.dll differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..42f46a1 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# sipgate Faxdrucker v4.1.0+ +The sipgate Faxdrucker is based on the PdfScribe Project from [stchan](https://github.com/stchan/PdfScribe). +We added the functionality to send the created PDF with a sipgate faxline to a recipient of your choice. + +## License +The original Project PdfScribe, and thus the sipgate Faxdrucker, are AGPL licensed. + +The application links to, and distributes the following third party components: + +* Microsoft Postscript Printer Driver (V3) +* Ghostscript (64-bit) +* Redmon 1.9 (64-bit) +* AutoUpdater.NET +* SharpVectors +* Mixpanel + +## Requirements +For development purposes a (Virtual) Machine with Windows and an IDE suitable for C# is required. + +* 64-bit Windows 7 or later +* .NET Framework 4.6.1 or later +* Visual Studio 19/ Rider +* [Wix Toolset](https://wixtoolset.org/releases/) \ No newline at end of file diff --git a/SipgateFaxdrucker.sln b/SipgateFaxdrucker.sln new file mode 100644 index 0000000..fa887fd --- /dev/null +++ b/SipgateFaxdrucker.sln @@ -0,0 +1,111 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SipgateFaxdruckerCore", "SipgateFaxdruckerCore\SipgateFaxdruckerCore.csproj", "{1EAD8E9A-A123-4C37-B31E-AEE1354DF003}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SipgateFaxdrucker", "SipgateFaxdrucker\SipgateFaxdrucker.csproj", "{09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SipgateFaxdruckerInstallCustomAction", "SipgateFaxdruckerInstallCustomAction\SipgateFaxdruckerInstallCustomAction.csproj", "{E8679E1B-8C89-4201-97D5-7E43C5A486C9}" +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "SipgateFaxdruckerInstall", "SipgateFaxdruckerInstall\SipgateFaxdruckerInstall.wixproj", "{3C255536-A7F1-4913-9C7F-966DFFEE01BC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SipgateFaxdruckerTests", "SipgateFaxdruckerTests\SipgateFaxdruckerTests.csproj", "{8562A5BC-A70E-40DD-A7E7-5611D332A983}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ia64 = Debug|ia64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ia64 = Release|ia64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|ia64.ActiveCfg = Debug|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|ia64.Build.0 = Debug|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|x64.ActiveCfg = Debug|x64 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|x64.Build.0 = Debug|x64 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|x86.ActiveCfg = Debug|x86 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Debug|x86.Build.0 = Debug|x86 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|Any CPU.Build.0 = Release|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|ia64.ActiveCfg = Release|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|ia64.Build.0 = Release|Any CPU + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x64.ActiveCfg = Release|x64 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x64.Build.0 = Release|x64 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x86.ActiveCfg = Release|x86 + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x86.Build.0 = Release|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|ia64.ActiveCfg = Debug|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|ia64.Build.0 = Debug|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x64.ActiveCfg = Debug|x64 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x64.Build.0 = Debug|x64 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x86.ActiveCfg = Debug|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x86.Build.0 = Debug|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|Any CPU.Build.0 = Release|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|ia64.ActiveCfg = Release|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|ia64.Build.0 = Release|Any CPU + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x64.ActiveCfg = Release|x64 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x64.Build.0 = Release|x64 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x86.ActiveCfg = Release|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x86.Build.0 = Release|x86 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|ia64.ActiveCfg = Debug|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|ia64.Build.0 = Debug|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|x64.ActiveCfg = Debug|x64 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|x64.Build.0 = Debug|x64 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|x86.ActiveCfg = Debug|x86 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Debug|x86.Build.0 = Debug|x86 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|Any CPU.Build.0 = Release|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|ia64.ActiveCfg = Release|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|ia64.Build.0 = Release|Any CPU + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|x64.ActiveCfg = Release|x64 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|x64.Build.0 = Release|x64 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|x86.ActiveCfg = Release|x86 + {E8679E1B-8C89-4201-97D5-7E43C5A486C9}.Release|x86.Build.0 = Release|x86 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Debug|Any CPU.ActiveCfg = Debug|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Debug|ia64.ActiveCfg = Debug|ia64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Debug|ia64.Build.0 = Debug|ia64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Debug|x64.ActiveCfg = Debug|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Debug|x86.ActiveCfg = Debug|x86 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Debug|x86.Build.0 = Debug|x86 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|Any CPU.ActiveCfg = Release|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|Any CPU.Build.0 = Release|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|ia64.ActiveCfg = Release|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|ia64.Build.0 = Release|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|x64.ActiveCfg = Release|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|x64.Build.0 = Release|x64 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|x86.ActiveCfg = Release|x86 + {3C255536-A7F1-4913-9C7F-966DFFEE01BC}.Release|x86.Build.0 = Release|x86 + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|ia64.ActiveCfg = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|ia64.Build.0 = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|x64.ActiveCfg = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|x64.Build.0 = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|x86.ActiveCfg = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Debug|x86.Build.0 = Debug|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Release|ia64.ActiveCfg = Release|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Release|ia64.Build.0 = Release|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Release|x64.ActiveCfg = Release|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Release|x86.ActiveCfg = Release|Any CPU + {8562A5BC-A70E-40DD-A7E7-5611D332A983}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3B5FB176-0EF6-421E-BF33-18A488C9C089} + EndGlobalSection +EndGlobal diff --git a/SipgateFaxdrucker.sln.DotSettings b/SipgateFaxdrucker.sln.DotSettings new file mode 100644 index 0000000..a85f915 --- /dev/null +++ b/SipgateFaxdrucker.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/SipgateFaxdrucker/App.config b/SipgateFaxdrucker/App.config new file mode 100644 index 0000000..c8e768e --- /dev/null +++ b/SipgateFaxdrucker/App.config @@ -0,0 +1,75 @@ + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + https://api.sipgate.com + + + https://login.sipgate.com + + + sipgate_faxdrucker_win + + + faxdrucker + + + + + + + + + + + + + + + + + + + + + + + + + + + 7 + + + https://sipgate-faxdrucker.s3.eu-central-1.amazonaws.com/version.xml + + + ba6490d191f97adf977a1293a1084b53 + + + 5e2eedfb2db9a53766edab1380f6017e + + + + \ No newline at end of file diff --git a/SipgateFaxdrucker/Authentication.cs b/SipgateFaxdrucker/Authentication.cs new file mode 100644 index 0000000..03b68bf --- /dev/null +++ b/SipgateFaxdrucker/Authentication.cs @@ -0,0 +1,446 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using Newtonsoft.Json; +using SipgateFaxdrucker.Properties; + +namespace SipgateFaxdrucker +{ + public class Authentication + { + private readonly string _clientId = Settings.Default.ClientId; +#if DEBUG + private static string _keycloakBaseUrl = "https://login.dev.sipgate.com"; +#else + private static string _keycloakBaseUrl = Settings.Default.LoginBaseUrl; +#endif + + private readonly string _tokenUrl = _keycloakBaseUrl + + @"/auth/realms/sipgate-apps/protocol/openid-connect/token"; + + private readonly string _loginUrl = _keycloakBaseUrl + + @"/auth/realms/sipgate-apps/protocol/openid-connect/auth"; + + private readonly string _logoutUrl = _keycloakBaseUrl + + @"/auth/realms/sipgate-apps/protocol/openid-connect/logout"; + + private const string GrantType = "authorization_code"; + private readonly string _state = RandomDataBase64Url(32); + private const string ResponseType = "code"; + public readonly string redirectUri; + private const string Scope = "faxlines:read sessions:fax:write history:read groups:faxlines:read offline_access contacts:read balance:read"; + + private static int GetRandomUnusedPort() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + var port = ((IPEndPoint)listener.LocalEndpoint).Port; + listener.Stop(); + return port; + } + + public Authentication() + { + redirectUri = $"http://{IPAddress.Loopback}:{GetRandomUnusedPort()}/"; + } + + public HttpListener CreateLoginBrowserWindow() + { + // Creates an HttpListener to listen for requests on that redirect URI. + var http = new HttpListener(); + http.Prefixes.Add(redirectUri); + http.Start(); + + // Creates the OAuth 2.0 authorization request. + NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty); + queryString.Add("response_type", ResponseType); + queryString.Add("client_id", _clientId); + queryString.Add("redirect_uri", redirectUri); + queryString.Add("state", _state); + queryString.Add("scope", Scope); + + System.Diagnostics.Process.Start(_loginUrl + "?" + queryString); + + return http; + } + + public void SendHttpResponse(HttpListenerContext context, bool success) + { + var response = context.Response; + response.AddHeader("Content-Type", "text/html"); + + var assembly = Assembly.GetExecutingAssembly(); + + var resourceName = "SipgateFaxdrucker.RedirectionPage.html"; + if (!success) + { + resourceName = "SipgateFaxdrucker.RedirectionPageFailure.html"; + } + + + using (var responseOutput = response.OutputStream) + using (var stream = assembly.GetManifestResourceStream(resourceName)) + { + stream?.CopyTo(responseOutput); + } + + response.OutputStream.Close(); + Utils.LogInformation("Sent response page to browser."); + } + + + /// + /// Returns URI-safe data with a given input length. + /// + /// Input length (nb. output will be longer) + /// + private static string RandomDataBase64Url(uint length) + { + RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); + byte[] bytes = new byte[length]; + rng.GetBytes(bytes); + return Base64UrlencodeNoPadding(bytes); + } + + /// + /// Base64url no-padding encodes the given input buffer. + /// + /// + /// + private static string Base64UrlencodeNoPadding(byte[] buffer) + { + string base64 = Convert.ToBase64String(buffer); + + // Converts base64 to base64url. + base64 = base64.Replace("+", "-"); + base64 = base64.Replace("/", "_"); + // Strips padding. + base64 = base64.Replace("=", ""); + + return base64; + } + + public async Task AwaitResponse(HttpListener httpListener) + { + var context = await httpListener.GetContextAsync(); + return context; + } + + public string ProcessResult(HttpListenerContext context) + { + // Checks for errors. + if (context.Request.QueryString.Get("error") != null) + { + throw new AuthorizationException(context.Request.QueryString.Get("error")); + } + + if (context.Request.QueryString.Get("code") == null + || context.Request.QueryString.Get("state") == null) + { + MessageBox.Show("Malformed authorization response. " + context.Request.QueryString); + throw new AuthorizationException(context.Request.QueryString.Get("error")); + } + + // extracts the code + var code = context.Request.QueryString.Get("code"); + var incomingState = context.Request.QueryString.Get("state"); + + // Compares the receieved state to the expected value, to ensure that + // this app made the request which resulted in authorization. + if (incomingState != _state) + { + MessageBox.Show($"Received request with invalid state ({incomingState})"); + throw new AuthorizationException(context.Request.QueryString.Get("error")); + } + + // Starts the code exchange at the Token Endpoint. + return code; + } + + public async Task PerformLogout(SipgateCredentials credentials) + { + try + { + var refreshToken = credentials.RefreshToken; + var accessToken = credentials.AccessToken; + + if (refreshToken == "") + { + Utils.LogError($"Missing refresh token: {refreshToken}"); + return false; + } + + if (accessToken == "") + { + Utils.LogError($"Missing access token: {accessToken}"); + return false; + } + + HttpWebRequest tokenRequest = (HttpWebRequest)WebRequest.Create(_logoutUrl); + + NameValueCollection tokenRequestBody = System.Web.HttpUtility.ParseQueryString(string.Empty); + tokenRequestBody.Add("client_id", _clientId); + tokenRequestBody.Add("refresh_token", refreshToken); + + byte[] byteVersion = Encoding.ASCII.GetBytes($"{tokenRequestBody}"); + + tokenRequest.Method = "POST"; + tokenRequest.ContentType = "application/x-www-form-urlencoded"; + tokenRequest.Accept = "application/json"; + tokenRequest.Headers["Authorization"] = $"Bearer {accessToken}"; + + Stream stream = tokenRequest.GetRequestStream(); + await stream.WriteAsync(byteVersion, 0, byteVersion.Length); + stream.Close(); + + + WebResponse tokenResponse = await tokenRequest.GetResponseAsync(); + + var responseStream = tokenResponse.GetResponseStream(); + if (responseStream == null) + { + return false; + } + using (StreamReader reader = + new StreamReader(responseStream)) + { + string responseText = await reader.ReadToEndAsync(); + Utils.LogInformation("responseText: " + responseText); + return true; + + } + } + catch (Exception e) + { + Utils.LogCritical($"exception on logout: {e.Message}-{e.GetType()}"); + return false; + } + + } + + public async Task PerformCodeExchange(string code) + { + HttpWebRequest tokenRequest = (HttpWebRequest)WebRequest.Create(_tokenUrl); + + try + { + SipgateCredentials sipgateCredentials = await ProcessCodeResponse(await PrepareCodeExchangeRequest(tokenRequest, code)); + + return sipgateCredentials; + } + catch (WebException ex) + { + if (ex.Status == WebExceptionStatus.NameResolutionFailure) + { + throw new NoInternetConnectionException(); + } + + if (ex.Status == WebExceptionStatus.ProtocolError) + { + if (ex.Response is HttpWebResponse response) + { + var responseStream = response.GetResponseStream(); + if (responseStream == null) + { + return null; + } + + using (StreamReader reader = new StreamReader(responseStream)) + { + string responseText = await reader.ReadToEndAsync(); + throw new Exception(responseText); + } + } + } + + Utils.LogCritical($"could not refresh token: {ex.Message} ({ex.Status})"); + return null; + } + catch (Exception e) + { + Utils.LogCritical($"Could not perform code exchange: {e.StackTrace} {e.GetType()}"); + return null; + } + + + } + + private async Task PrepareCodeExchangeRequest(HttpWebRequest tokenRequest, string code) + { + NameValueCollection tokenRequestBody = System.Web.HttpUtility.ParseQueryString(string.Empty); + tokenRequestBody.Add("code", code); + tokenRequestBody.Add("client_id", _clientId); + tokenRequestBody.Add("redirect_uri", redirectUri); + tokenRequestBody.Add("scope", Scope); + tokenRequestBody.Add("grant_type", GrantType); + + byte[] byteVersion = Encoding.ASCII.GetBytes($"{tokenRequestBody}"); + + tokenRequest.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; + tokenRequest.Method = "POST"; + tokenRequest.ContentType = "application/x-www-form-urlencoded"; + tokenRequest.Accept = "application/json"; + tokenRequest.ContentLength = byteVersion.Length; + + try + { + Stream stream = tokenRequest.GetRequestStream(); + await stream.WriteAsync(byteVersion, 0, byteVersion.Length); + stream.Close(); + } + catch (Exception e) + { + Utils.LogCritical("Could not perform code exchange:" + e.Message); + return null; + } + + return tokenRequest; + } + + private async Task ProcessCodeResponse(HttpWebRequest tokenRequest) + { + WebResponse tokenResponse = await tokenRequest.GetResponseAsync(); + + var responseStream = tokenResponse.GetResponseStream(); + if (responseStream == null) + { + return null; + } + + using (StreamReader reader = + new StreamReader(responseStream)) + { + string responseText = await reader.ReadToEndAsync(); + Dictionary tokenEndpointDecoded = + JsonConvert.DeserializeObject>(responseText); + return new SipgateCredentials(tokenEndpointDecoded["access_token"], tokenEndpointDecoded["refresh_token"]); + } + } + + public async Task RefreshAccessToken(string refreshToken) + { + HttpWebRequest tokenRequest = (HttpWebRequest)WebRequest.Create(_tokenUrl); + try + { + await PrepareTokenRequest(tokenRequest, refreshToken); + + SipgateCredentials credentials = await ProcessRefreshReponse(tokenRequest); + return credentials; + }catch (WebException wex) + { + + if (wex.Status == WebExceptionStatus.NameResolutionFailure || wex.Status == WebExceptionStatus.ConnectFailure) + { + throw new NoInternetConnectionException(); + } + + if (wex.Status == WebExceptionStatus.ProtocolError) + { + if (wex.Response is HttpWebResponse response) + { + var responseStream = response.GetResponseStream(); + if (responseStream == null) + { + return null; + } + + using (StreamReader reader = new StreamReader(responseStream)) + { + string responseText = await reader.ReadToEndAsync(); + throw new InvalidRefreshTokenException(responseText); + } + } + } + + Utils.LogCritical($"could not refresh token: {wex.Status}"); + return null; + } + catch (Exception e) + { + Utils.LogCritical($"could not refresh token: {e.Message} ({e.GetType()})"); + return null; + } + } + + private async Task PrepareTokenRequest(HttpWebRequest tokenRequest, string refreshToken) + { + NameValueCollection tokenRequestBody = System.Web.HttpUtility.ParseQueryString(string.Empty); + tokenRequestBody.Add("refresh_token", refreshToken); + tokenRequestBody.Add("client_id", _clientId); + tokenRequestBody.Add("grant_type", "refresh_token"); + + byte[] byteVersion = Encoding.ASCII.GetBytes("" + tokenRequestBody); + + tokenRequest.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; + tokenRequest.Method = "POST"; + tokenRequest.ContentType = "application/x-www-form-urlencoded"; + tokenRequest.Accept = "application/json"; + tokenRequest.ContentLength = byteVersion.Length; + + Stream stream = null; + try + { + stream = tokenRequest.GetRequestStream(); + await stream.WriteAsync(byteVersion, 0, byteVersion.Length); + stream.Close(); + return true; + } + catch (WebException wex) + { + Utils.LogCritical($"get request stream failed:{wex}"); + if (stream != null) stream.Close(); + throw; + } + } + + private async Task ProcessRefreshReponse(HttpWebRequest tokenRequest) + { + WebResponse tokenResponse = await tokenRequest.GetResponseAsync(); + + var responseStream = tokenResponse.GetResponseStream(); + if (responseStream == null) + { + return null; + } + + using (StreamReader reader = + new StreamReader(responseStream)) + { + string responseText = await reader.ReadToEndAsync(); + Dictionary tokenEndpointDecoded = + JsonConvert.DeserializeObject>(responseText); + return new SipgateCredentials(tokenEndpointDecoded["access_token"], tokenEndpointDecoded["refresh_token"]); + } + } + + public class InvalidRefreshTokenException : Exception + { + public InvalidRefreshTokenException(string message) + : base(message) + { + } + } + + public class AuthorizationException : Exception + { + public AuthorizationException(string message) + : base(message) + { + } + } + + public class NoInternetConnectionException : WebException + { + } + } + + +} \ No newline at end of file diff --git a/SipgateFaxdrucker/Contact.cs b/SipgateFaxdrucker/Contact.cs new file mode 100644 index 0000000..a1ff2f5 --- /dev/null +++ b/SipgateFaxdrucker/Contact.cs @@ -0,0 +1,72 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace SipgateFaxdrucker +{ + public class Contact : INotifyPropertyChanged + { + public Contact(string name, string number, string company, bool isNoContactFallback = false) + { + Name = name; + Number = number; + Company = company; + IsNoContactFallback = isNoContactFallback; + GenerateFaxlineVariation(number); + } + + private void GenerateFaxlineVariation(string number) + { + if (number.StartsWith("0")) + { + NationalFaxLine = number; + InternationalFaxLine = number.Remove(0, 1).Insert(0, "+49"); + IsGermanFaxLine = true; + return; + } + + if (number.StartsWith("+49")) + { + InternationalFaxLine = number; + NationalFaxLine = number.Remove(0, 3).Insert(0, "0"); + IsGermanFaxLine = true; + return; + } + + IsGermanFaxLine = false; + Number = number; + } + + public bool IsNoContactFallback { get; } + public string Name { get; } + public string Number { get; private set; } + public string Company { get; } + public string NationalFaxLine { get; private set; } + public string InternationalFaxLine { get; private set; } + public bool IsGermanFaxLine { get; private set; } + + public string DisplayCompany => string.IsNullOrEmpty(Company) ? "" : $" ({Company})"; + + public override string ToString() + { + return $"{Name} {Company} {Number}"; + } + + public void ChangeNumber(string number) + { + Number = number; + OnPropertyChanged(nameof(Number)); + } + + public bool IsValidFaxNumber() + { + return !IsNoContactFallback && Utils.GetNumberValidationResult(Number).wasSuccessful; + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/Converter/BooleanToInvertedVisibilityConverter.cs b/SipgateFaxdrucker/Converter/BooleanToInvertedVisibilityConverter.cs new file mode 100644 index 0000000..b9f8323 --- /dev/null +++ b/SipgateFaxdrucker/Converter/BooleanToInvertedVisibilityConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace SipgateFaxdrucker.Converter +{ + public class BooleanToInvertedVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is bool boolToBeInverted) + { + return boolToBeInverted ? Visibility.Collapsed : Visibility.Visible; + } + + return Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/Converter/BooleanToVisibilityConverter.cs b/SipgateFaxdrucker/Converter/BooleanToVisibilityConverter.cs new file mode 100644 index 0000000..fc5aeeb --- /dev/null +++ b/SipgateFaxdrucker/Converter/BooleanToVisibilityConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace SipgateFaxdrucker.Converter +{ + public class BooleanToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is bool visibilityBoolean) + { + return visibilityBoolean ? Visibility.Visible : Visibility.Collapsed; + } + + return Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/CredentialManager.cs b/SipgateFaxdrucker/CredentialManager.cs new file mode 100644 index 0000000..50eea90 --- /dev/null +++ b/SipgateFaxdrucker/CredentialManager.cs @@ -0,0 +1,139 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker +{ + + public class CredentialManager + { + private SipgateCredentials _credentials; + private readonly byte[] _sAdditionalEntropy = { 9, 8, 7, 6, 5 }; + + public CredentialManager() + { + Utils.LogInformation("Created CredentialManager"); + } + + private string GetConfigPath() + { + try + { + var localApplicationDataDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + string[] configPaths = { localApplicationDataDirectory, $@"{Utils.appName}" }; + string configPath = Path.Combine(configPaths); + + if (!Directory.Exists(configPath)) + { + Directory.CreateDirectory(configPath); + } + + string[] configFilePaths = { configPath, @"config.dat" }; + return Path.Combine(configFilePaths); + } + catch (Exception e) + { + Utils.LogCritical($"Error creating config path for credentials ({e.Message})"); + return null; + } + } + + private byte[] Protect(byte[] data) + { + try + { + // Encrypt the data using DataProtectionScope.CurrentUser. The result can be decrypted + // only by the same current user. + return ProtectedData.Protect(data, _sAdditionalEntropy, DataProtectionScope.CurrentUser); + } + catch (CryptographicException e) + { + Console.WriteLine("Data was not encrypted. An error occurred."); + Console.WriteLine(e.ToString()); + return null; + } + } + + private byte[] Unprotect(byte[] data) + { + try + { + //Decrypt the data using DataProtectionScope.CurrentUser. + return ProtectedData.Unprotect(data, _sAdditionalEntropy, DataProtectionScope.CurrentUser); + } + catch (CryptographicException e) + { + Console.WriteLine("Data was not decrypted. An error occurred."); + Console.WriteLine(e.ToString()); + return null; + } + } + + private SipgateCredentials LoadCredentials() + { + try + { + string directory = GetConfigPath(); + if (!File.Exists(directory)) + { + return null; + } + + byte[] protectedContent = File.ReadAllBytes(directory); + + string jsonString = Encoding.Unicode.GetString(Unprotect(protectedContent)); + + return JsonConvert.DeserializeObject(jsonString); + } + catch (Exception e) + { + Utils.LogCritical($"error loading credentials: {e.Message}"); + return null; + } + } + + public void RemoveCredentials() + { + string directory = GetConfigPath(); + if (File.Exists(directory)) + { + File.Delete(directory); + } + _credentials = null; + } + + public SipgateCredentials GetCredentials() + { + return _credentials ?? (_credentials = LoadCredentials()); + } + + private void SaveCredentials() + { + try + { + string directory = GetConfigPath(); + + string jsonString = JsonConvert.SerializeObject(_credentials); + + File.WriteAllBytes(directory, Protect(Encoding.Unicode.GetBytes(jsonString))); + } + catch (Exception e) + { + Utils.LogCritical($"error saving credentials: {e.Message}"); + } + } + + public void SaveCredentials(SipgateCredentials newCredentials) + { + _credentials = newCredentials; + SaveCredentials(); + } + + public bool IsLoggedIn() + { + return GetCredentials() != null && GetCredentials().AccessToken != ""; + } + } +} diff --git a/SipgateFaxdrucker/CustomCombobox.cs b/SipgateFaxdrucker/CustomCombobox.cs new file mode 100644 index 0000000..f47767c --- /dev/null +++ b/SipgateFaxdrucker/CustomCombobox.cs @@ -0,0 +1,56 @@ +using System; +using System.Windows; +using System.Windows.Controls; + +namespace SipgateFaxdrucker +{ + class CustomCombobox : ComboBox + { + private int _caretPosition; + private TextBox _textBox; + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + var element = GetTemplateChild("PART_EditableTextBox"); + if (element != null) + { + _textBox = (TextBox)element; + _textBox.SelectionChanged += OnDropSelectionChanged; + } + } + + protected override void OnDropDownClosed(EventArgs e) + { + base.OnDropDownClosed(e); + + if (_textBox.SelectionLength > 0) + { + _caretPosition = _textBox.SelectionLength; // caretPosition must be set to TextBox's SelectionLength + _textBox.CaretIndex = _caretPosition; + } + if (_textBox.SelectionLength == 0 && _textBox.CaretIndex != 0) + { + _caretPosition = _textBox.CaretIndex; + } + } + + private void OnDropSelectionChanged(object sender, RoutedEventArgs e) + { + TextBox txt = (TextBox)sender; + + if (IsDropDownOpen && txt.SelectionLength > 0) + { + _caretPosition = txt.SelectionLength; // caretPosition must be set to TextBox's SelectionLength + txt.CaretIndex = _caretPosition; + } + if (txt.SelectionLength == 0 && txt.CaretIndex != 0) + { + _caretPosition = txt.CaretIndex; + } + } + + + } +} diff --git a/SipgateFaxdrucker/ErrorDialog.cs b/SipgateFaxdrucker/ErrorDialog.cs new file mode 100644 index 0000000..28fc711 --- /dev/null +++ b/SipgateFaxdrucker/ErrorDialog.cs @@ -0,0 +1,156 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace SipgateFaxdrucker +{ + public class ErrorDialog + { + #region Message constants + + const string ErrorDialogInstructionPdfGeneration = "There was a PDF generation error."; + const string ErrorDialogInstructionCouldNotWrite = "Could not create the output file."; + const string ErrorDialogInstructionUnexpectedError = "There was an internal error. Enable tracing for details."; + const string ErrorDialogTextGhostScriptConversion = "Ghostscript error code {0}."; + const string ErrorDialogCaption = "sipgate Faxdrucker"; + + const string ErrorDialogOutputFilenameInvalid = + "Output file path is not valid. Check the \"OutputFile\" setting in the config file."; + + const string ErrorDialogOutputFilenameTooLong = + "Output file path too long. Check the \"OutputFile\" setting in the config file."; + + const string ErrorDialogOutputFileAccessDenied = "Access denied - check permissions on output folder."; + + const string WarnFileNotDeleted = "{0} could not be deleted."; + + #endregion + + private TraceSource _logEventSource; + + public ErrorDialog(TraceSource logEventSource) + { + this._logEventSource = logEventSource; + } + + public void Show(Exception e) + { + if (e.InnerException is ArgumentException || e.InnerException is NotSupportedException || + e.InnerException is DirectoryNotFoundException) + { + { + _logEventSource.TraceEvent(TraceEventType.Error, + (int) TraceEventType.Error, + ErrorDialogOutputFilenameInvalid + Environment.NewLine + + "Exception message: " + e.Message); + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogOutputFilenameInvalid); + } + } + else + { + DisplayErrorMessage(ErrorDialogCaption, "General Error: " + e); + } + } + + public void Show(ExternalException ghostscriptEx) + { + // Ghostscript error + _logEventSource.TraceEvent(TraceEventType.Error, + (int) TraceEventType.Error, + String.Format(ErrorDialogTextGhostScriptConversion, ghostscriptEx.ErrorCode.ToString()) + + Environment.NewLine + + "Exception message: " + ghostscriptEx.Message); + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogInstructionPdfGeneration + Environment.NewLine + + String.Format(ErrorDialogTextGhostScriptConversion, ghostscriptEx.ErrorCode.ToString())); + } + + public void Show(PathTooLongException ex) + { + // filename is greater than 260 characters + _logEventSource.TraceEvent(TraceEventType.Error, + (int) TraceEventType.Error, + ErrorDialogOutputFilenameTooLong + Environment.NewLine + + "Exception message: " + ex.Message); + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogOutputFilenameTooLong); + } + + public void Show(UnauthorizedAccessException ex) + { + _logEventSource.TraceEvent(TraceEventType.Error, + (int) TraceEventType.Error, + ErrorDialogOutputFileAccessDenied + Environment.NewLine + + "Exception message: " + ex.Message); + // Can't write to target dir + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogOutputFileAccessDenied); + } + + public void Show(IOException ioEx, String outputFilename) + { + // We couldn't delete, or create a file + // because it was in use + _logEventSource.TraceEvent(TraceEventType.Error, + (int) TraceEventType.Error, + ErrorDialogInstructionCouldNotWrite + + Environment.NewLine + + "Exception message: " + ioEx.Message); + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogInstructionCouldNotWrite + Environment.NewLine + + $"{outputFilename} is in use."); + } + + public void Show(UnauthorizedAccessException unauthorizedEx, String outputFilename) + { + // Couldn't delete a file + // because it was set to readonly + // or couldn't create a file + // because of permissions issues + _logEventSource.TraceEvent(TraceEventType.Error, + (int) TraceEventType.Error, + ErrorDialogInstructionCouldNotWrite + + Environment.NewLine + + "Exception message: " + unauthorizedEx.Message); + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogInstructionCouldNotWrite + Environment.NewLine + + $"Insufficient privileges to either create or delete {outputFilename}"); + } + + + public void HandleFileNotDeleted(string standardInputFilename) + { + _logEventSource.TraceEvent(TraceEventType.Warning, + (int) TraceEventType.Warning, + String.Format(WarnFileNotDeleted, standardInputFilename)); + } + + public void HandleUnhandledException(UnhandledExceptionEventArgs e) + { + _logEventSource.TraceEvent(TraceEventType.Critical, + (int) TraceEventType.Critical, + ((Exception) e.ExceptionObject).Message + Environment.NewLine + + ((Exception) e.ExceptionObject).StackTrace); + DisplayErrorMessage(ErrorDialogCaption, + ErrorDialogInstructionUnexpectedError); + } + /// + /// Displays up a topmost, OK-only message box for the error message + /// + /// The box's caption + /// The box's message + private void DisplayErrorMessage(String boxCaption, + String boxMessage) + { + MessageBox.Show(boxMessage, + boxCaption, + MessageBoxButtons.OK, + MessageBoxIcon.Error, + MessageBoxDefaultButton.Button1, + MessageBoxOptions.DefaultDesktopOnly); + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/FaxManager.cs b/SipgateFaxdrucker/FaxManager.cs new file mode 100644 index 0000000..db09087 --- /dev/null +++ b/SipgateFaxdrucker/FaxManager.cs @@ -0,0 +1,140 @@ +using Microsoft.Rest; +using System; +using System.Windows; +using System.Threading.Tasks; +using PhoneNumbers; +using SipgateFaxdrucker.SipgateAPI; +using SipgateFaxdrucker.SipgateAPI.Models; + +namespace SipgateFaxdrucker +{ + public class FaxManager + { + public string FileName { get; set; } + public PhoneNumber TargetNumber { get; set; } + + public async Task GetFaxLineAsync(SipgateApi api) + { + try + { + Utils.LogInformation("API: Get user info...", 1); + UserinfoResponse userinfo = await api.UserinfoAsync(); + if (userinfo != null) + { + Utils.LogInformation($"API: Got user info: {userinfo.Sub}"); + } + else + { + Utils.LogInformation("API: Error fetching user info: "); + return null; + } + + Utils.LogInformation("API: Get fax lines info..."); + FaxlinesResponse faxlines = await api.GetUserFaxlinesAsync(userinfo.Sub); + Utils.LogInformation($"API: Got fax lines: {faxlines.Items.Count}"); + + return faxlines; + } + catch (Exception ex) + { + Utils.LogCritical($"API: Error fetching user info: {ex.Message}"); + return null; + } + } + + public async Task GetGroupFaxLineAsync(SipgateApi api) + { + try + { + + Utils.LogInformation("API: Get user info...", 2); + UserinfoResponse userinfo = await api.UserinfoAsync(); + Utils.LogInformation($"API: Got user info: {userinfo.Sub}"); + + Utils.LogInformation("API: Get group fax lines info..."); + GroupFaxlinesResponse faxlines = await api.GetGroupFaxlinesForUserAsync(userinfo.Sub); + Utils.LogInformation($"API: Got group fax lines: {faxlines.Items.Count}"); + + return faxlines; + } + catch (Exception e) + { + MessageBox.Show(e.Message, "get groupfaxlines"); + return null; + } + } + + + public async Task SendFileWithSipgateApi(string faxlineId, SipgateApi api) + { + var base64Content = await Task.Run(() => Utils.ConvertPdfToBase64(FileName)); + + Utils.LogInformation("Calling API...:"); + + try + { + if (faxlineId == null) + { + Utils.LogError("Fax could not be sent: No faxline found for logged in user"); + return null; + } + + Utils.LogInformation("Filename: " + FileName); + var faxDocumentName = $"fax_{DateTime.Now:dd-MM-yyyy-HH-mm}.pdf"; + Utils.LogInformation("faxName: " + faxDocumentName); + SendFaxRequest request = new SendFaxRequest + { + FaxlineId = faxlineId, + Filename = faxDocumentName, + Recipient = Utils.E164TargetNumber(TargetNumber), + Base64Content = base64Content, + }; + + Utils.LogInformation("Response received."); + + SendFaxSessionResponse response = await api.SendFaxAsync(request); + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + Utils.LogInformation($"Success! SessionID: {response.SessionId}"); + return response.SessionId; + } + else + { + Utils.LogError("Failed! Response code was: " + response.StatusCode); + return null; + } + } + catch (ValidationException) + { + throw; + } + catch (Exception ex) + { + Utils.LogError($"Error while sending fax: {ex.GetType()} {ex.Message} {ex.StackTrace}"); + return null; + } + } + } + + public class SelectableFaxline + { + public SelectableFaxline(FaxlineResponse faxline) + { + Id = faxline.Id; + Alias = faxline.Alias; + } + + public SelectableFaxline(GroupFaxlineResponse faxline) + { + Id = faxline.Id; + Alias = faxline.Alias; + } + + public string Id { get; } + + public string Alias { get; } + + + + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/FaxStatus.cs b/SipgateFaxdrucker/FaxStatus.cs new file mode 100644 index 0000000..8b0c8d2 --- /dev/null +++ b/SipgateFaxdrucker/FaxStatus.cs @@ -0,0 +1,98 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Windows.Media; +using System.Windows.Threading; +using System.Windows; +using SipgateFaxdrucker.SipgateAPI; +using SipgateFaxdrucker.SipgateAPI.Models; + +namespace SipgateFaxdrucker +{ + public class FaxStatus + { + private static Dictionary _status = new Dictionary + { + {"PENDING", new FaxStatusDetail("Warten auf Versand..." , Brushes.DarkOrange, false) }, + {"SENDING", new FaxStatusDetail("Fax wird versendet...", Brushes.DarkOrange, false)}, + {"FAILED", new FaxStatusDetail("Versand fehlgeschlagen", Brushes.Red, true)}, + {"SENT", new FaxStatusDetail("Fax erfolgreich versendet!", Brushes.Green, true)}, + }; + + private readonly string _sessionId; + private SipgateApi _api; + + public FaxStatus(string sessionId, SipgateApi sipgateApi) + { + this._sessionId = sessionId; + this._api = sipgateApi; + } + + private async Task CheckStatus() + { + HistoryEntryResponse historyResponse = await _api.GetHistoryByIdAsync(_sessionId); + + if (historyResponse == null) + { + return null; + } + + return historyResponse.FaxStatusType; + } + + public void PollForStatus(SipgateForm form) + { + var timer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(1)}; + + timer.Tick += async (sender, e) => + { + DispatcherTimer originalTimer = (DispatcherTimer)sender; + + string status; + try + { + status = await CheckStatus(); + } + catch (Exception ex) + { + form.TextSendStatus.Text = "Abfrage des Status fehlgeschlagen"; + Utils.LogCritical($"CheckStatus failed: {ex.Message}"); + originalTimer.Stop(); + return; + } + + if (status != null) + { + FaxStatusDetail faxStatusDetail = FaxStatus._status[status]; + if (faxStatusDetail != null) + { + form.TextSendStatus.Text = faxStatusDetail.Translation; + form.TextSendStatus.Foreground = faxStatusDetail.Color; + + if (faxStatusDetail.IsFinal) + { + form.BtnClose.Visibility = Visibility.Visible; + form.BtnMinimize.Visibility = Visibility.Collapsed; + originalTimer.Stop(); + } + } + } + }; + timer.Start(); + } + } + + public class FaxStatusDetail + { + public string Translation { get; } + public SolidColorBrush Color { get; } + public bool IsFinal { get; } + + public FaxStatusDetail(string translation, SolidColorBrush color, bool isFinal) + { + this.Translation = translation; + this.Color = color; + this.IsFinal = isFinal; + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/GhostScript/GhostScript32.cs b/SipgateFaxdrucker/GhostScript/GhostScript32.cs new file mode 100644 index 0000000..5deecc0 --- /dev/null +++ b/SipgateFaxdrucker/GhostScript/GhostScript32.cs @@ -0,0 +1,61 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows; + +namespace SipgateFaxdrucker.GhostScript +{ + internal class GhostScript32 + { + /* + This code was adapted from Matthew Ephraim's Ghostscript.Net project + external dll definitions moved into NativeMethods to + satisfy FxCop requirements + https://github.com/mephraim/ghostscriptsharp + */ + + /// + /// Calls the Ghostscript API with a collection of arguments to be passed to it + /// + public static void CallApi(string[] args) + { + // Get a pointer to an instance of the Ghostscript API and run the API with the current arguments + IntPtr gsInstancePtr; + lock (_resourceLock) + { + NativeMethods32.CreateAPIInstance(out gsInstancePtr, IntPtr.Zero); + try + { + int result = NativeMethods32.InitAPI(gsInstancePtr, args.Length, args); + + if (result < 0) + { + throw new ExternalException("Ghostscript conversion error", result); + } + } + catch (Exception e) + { + MessageBox.Show("ghostscript error" + e); + } + finally + { + Cleanup(gsInstancePtr); + } + } + } + + /// + /// Frees up the memory used for the API arguments and clears the Ghostscript API instance + /// + private static void Cleanup(IntPtr gsInstancePtr) + { + NativeMethods32.ExitAPI(gsInstancePtr); + NativeMethods32.DeleteAPIInstance(gsInstancePtr); + } + + + /// + /// GS can only support a single instance, so we need to bottleneck any multi-threaded systems. + /// + private static object _resourceLock = new object(); + } +} diff --git a/SipgateFaxdrucker/GhostScript/GhostScript64.cs b/SipgateFaxdrucker/GhostScript/GhostScript64.cs new file mode 100644 index 0000000..3c933d8 --- /dev/null +++ b/SipgateFaxdrucker/GhostScript/GhostScript64.cs @@ -0,0 +1,61 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows; + +namespace SipgateFaxdrucker.GhostScript +{ + internal class GhostScript64 + { + /* + This code was adapted from Matthew Ephraim's Ghostscript.Net project + external dll definitions moved into NativeMethods to + satisfy FxCop requirements + https://github.com/mephraim/ghostscriptsharp + */ + + /// + /// Calls the Ghostscript API with a collection of arguments to be passed to it + /// + public static void CallApi(string[] args) + { + // Get a pointer to an instance of the Ghostscript API and run the API with the current arguments + IntPtr gsInstancePtr; + lock (_resourceLock) + { + NativeMethods64.CreateAPIInstance(out gsInstancePtr, IntPtr.Zero); + try + { + int result = NativeMethods64.InitAPI(gsInstancePtr, args.Length, args); + + if (result < 0) + { + throw new ExternalException("Ghostscript conversion error", result); + } + } + catch (Exception e) + { + MessageBox.Show("ghostscript error" + e); + } + finally + { + Cleanup(gsInstancePtr); + } + } + } + + /// + /// Frees up the memory used for the API arguments and clears the Ghostscript API instance + /// + private static void Cleanup(IntPtr gsInstancePtr) + { + NativeMethods64.ExitAPI(gsInstancePtr); + NativeMethods64.DeleteAPIInstance(gsInstancePtr); + } + + + /// + /// GS can only support a single instance, so we need to bottleneck any multi-threaded systems. + /// + private static object _resourceLock = new object(); + } +} diff --git a/SipgateFaxdrucker/GhostScript/GhostScriptRunner.cs b/SipgateFaxdrucker/GhostScript/GhostScriptRunner.cs new file mode 100644 index 0000000..2404ded --- /dev/null +++ b/SipgateFaxdrucker/GhostScript/GhostScriptRunner.cs @@ -0,0 +1,140 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +namespace SipgateFaxdrucker.GhostScript +{ + public class GhostScriptRunner + { + + private String _outputFilename = String.Empty; + + const string TraceSourceName = "SipgateFaxdrucker"; + private static readonly TraceSource LogEventSource = new TraceSource(TraceSourceName); + + + public string Print(String standardInputFilename) + { + ErrorDialog errorDialog = new ErrorDialog(LogEventSource); + + var sizeInfo = Utils.GetFileSize(standardInputFilename); + Utils.LogCritical("standardinputfilename before : "+ sizeInfo); + try + { + using (BinaryReader standardInputReader = new BinaryReader(Console.OpenStandardInput())) + { + using (FileStream standardInputFile = + new FileStream(standardInputFilename, FileMode.Create, FileAccess.ReadWrite)) + { + standardInputReader.BaseStream.CopyTo(standardInputFile); + + } + } + + if (GetPdfOutputFilename(ref _outputFilename)) + { + File.Delete(_outputFilename); + String[] ghostScriptArguments = + { + "-dBATCH", "-dNOPAUSE", "-dSAFER", "-sDEVICE=pdfwrite", "-dCompatibilityLevel=1.4", "-dPDFSETTINGS=/ebook", + $"-sOutputFile={_outputFilename}", standardInputFilename, + "-c", @"[/Creator(SipgateFaxdrucker 4.0.0 (PSCRIPT5)) /DOCINFO pdfmark", "-f" + }; + + // the current process will usually run in 32 bits, but that also depends on the OS, spooler, printer drivers, executable location, etc. + // call the ghostscript dll accordingly + if (Environment.Is64BitOperatingSystem && Environment.Is64BitProcess) + { + GhostScript64.CallApi(ghostScriptArguments); + } + else + { + GhostScript32.CallApi(ghostScriptArguments); + } + } + } + catch (IOException ioEx) + { + errorDialog.Show(ioEx,_outputFilename); + } + catch (UnauthorizedAccessException unauthorizedEx) + { + errorDialog.Show(unauthorizedEx, _outputFilename); + } + catch (ExternalException ghostscriptEx) + { + errorDialog.Show(ghostscriptEx); + } + catch (Exception ex) + { + errorDialog.Show(ex); + } + finally + { + try + { + File.Delete(standardInputFilename); + } + catch + { + errorDialog.HandleFileNotDeleted(standardInputFilename); + } + LogEventSource.Flush(); + } + + return _outputFilename; + } + + private bool GetPdfOutputFilename(ref String outputFile) + { + bool filenameRetrieved = false; + ErrorDialog errorDialog = new ErrorDialog(LogEventSource); + + try + { + outputFile = GetOutputFilename(); + using (FileStream _ = File.Create(outputFile)) + { + // Tests if we can write to the destination + } + + File.Delete(outputFile); + filenameRetrieved = true; + } + catch (Exception ex) when (ex is ArgumentException || + ex is NotSupportedException || + ex is DirectoryNotFoundException) + { + errorDialog.Show(ex); + } + catch (PathTooLongException ex) + { + errorDialog.Show(ex); + } + catch (UnauthorizedAccessException ex) + { + errorDialog.Show(ex); + } + + return filenameRetrieved; + } + + private String GetOutputFilename() + { + var currentDateTimeString = DateTime.Now.ToString("dd-MM-yyyy HH-mm"); + var settingsPathPart = Path.GetTempPath(); + var completePath = settingsPathPart + currentDateTimeString + ".pdf"; + + String defaultOutputFilename = + Path.GetFullPath(completePath); + + // Check if there are any % characters - + // even though it's a legal Windows filename character, + // it is a special character to Ghostscript + if (defaultOutputFilename.Contains("%")) + throw new ArgumentException("OutputFile setting contains % character."); + return defaultOutputFilename; + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/GhostScript/NativeMethods32.cs b/SipgateFaxdrucker/GhostScript/NativeMethods32.cs new file mode 100644 index 0000000..ded8574 --- /dev/null +++ b/SipgateFaxdrucker/GhostScript/NativeMethods32.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.InteropServices; + +namespace SipgateFaxdrucker.GhostScript +{ + internal static class NativeMethods32 + { + /* + This code was adapted from Matthew Ephraim's Ghostscript.Net project - + external dll definitions moved into NativeMethods to + satisfy FxCop requirements + https://github.com/mephraim/ghostscriptsharp + */ + + #region Hooks into Ghostscript DLL + [DllImport("gsdll32.dll", EntryPoint = "gsapi_new_instance")] + internal static extern int CreateAPIInstance(out IntPtr pinstance, IntPtr callerHandle); + + [DllImport("gsdll32.dll", EntryPoint = "gsapi_init_with_args")] + internal static extern int InitAPI(IntPtr instance, int argc, string[] argv); + + [DllImport("gsdll32.dll", EntryPoint = "gsapi_exit")] + internal static extern int ExitAPI(IntPtr instance); + + [DllImport("gsdll32.dll", EntryPoint = "gsapi_delete_instance")] + internal static extern void DeleteAPIInstance(IntPtr instance); + #endregion + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern bool SetDllDirectory(string lpPathName); + } +} diff --git a/SipgateFaxdrucker/GhostScript/NativeMethods64.cs b/SipgateFaxdrucker/GhostScript/NativeMethods64.cs new file mode 100644 index 0000000..9637f03 --- /dev/null +++ b/SipgateFaxdrucker/GhostScript/NativeMethods64.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.InteropServices; + +namespace SipgateFaxdrucker.GhostScript +{ + internal static class NativeMethods64 + { + /* + This code was adapted from Matthew Ephraim's Ghostscript.Net project - + external dll definitions moved into NativeMethods to + satisfy FxCop requirements + https://github.com/mephraim/ghostscriptsharp + */ + + #region Hooks into Ghostscript DLL + [DllImport("gsdll64.dll", EntryPoint = "gsapi_new_instance")] + internal static extern int CreateAPIInstance(out IntPtr pinstance, IntPtr callerHandle); + + [DllImport("gsdll64.dll", EntryPoint = "gsapi_init_with_args")] + internal static extern int InitAPI(IntPtr instance, int argc, string[] argv); + + [DllImport("gsdll64.dll", EntryPoint = "gsapi_exit")] + internal static extern int ExitAPI(IntPtr instance); + + [DllImport("gsdll64.dll", EntryPoint = "gsapi_delete_instance")] + internal static extern void DeleteAPIInstance(IntPtr instance); + #endregion + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern bool SetDllDirectory(string lpPathName); + } +} diff --git a/SipgateFaxdrucker/GhostScript/Settings.cs b/SipgateFaxdrucker/GhostScript/Settings.cs new file mode 100644 index 0000000..e78abcf --- /dev/null +++ b/SipgateFaxdrucker/GhostScript/Settings.cs @@ -0,0 +1,30 @@ +using System; + +namespace SipgateFaxdrucker.Properties { + + + // This class allows you to handle specific events on the settings class: + // The SettingChanging event is raised before a setting's value is changed. + // The PropertyChanged event is raised after a setting's value is changed. + // The SettingsLoaded event is raised after the setting values are loaded. + // The SettingsSaving event is raised before the setting values are saved. + internal sealed partial class Settings { + public Settings() { + // // To add event handlers for saving and changing settings, uncomment the lines below: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Add code to handle the SettingChangingEvent event here. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Add code to handle the SettingsSaving event here. + } + } +} diff --git a/SipgateFaxdrucker/GhostScript/gsdll32.dll b/SipgateFaxdrucker/GhostScript/gsdll32.dll new file mode 100644 index 0000000..ea1dcc7 Binary files /dev/null and b/SipgateFaxdrucker/GhostScript/gsdll32.dll differ diff --git a/SipgateFaxdrucker/MainViewModel.cs b/SipgateFaxdrucker/MainViewModel.cs new file mode 100644 index 0000000..961cb81 --- /dev/null +++ b/SipgateFaxdrucker/MainViewModel.cs @@ -0,0 +1,100 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows.Data; + +namespace SipgateFaxdrucker +{ + public class MainViewModel : INotifyPropertyChanged + { + public MainViewModel() + { + Contacts = (CollectionView)new CollectionViewSource { Source = new ObservableCollection() }.View; + Contacts.Filter = DropDownFilter; + } + + #region ComboBox + + public CollectionView Contacts { get; } + + private Contact _selectedContact; + public Contact SelectedContact + { + get => _selectedContact; + set + { + if (value != null) + { + _selectedContact = value; + OnPropertyChanged(); + SearchText = _selectedContact.Number; + } + } + } + + private bool _comboOpen; + public bool ComboOpen + { + get => _comboOpen; + set + { + _comboOpen = value; + OnPropertyChanged(); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + private string _searchText; + public string SearchText + { + get => _searchText; + set + { + if (value != null) + { + _searchText = value; + OnPropertyChanged(); + if (SelectedContact == null || _searchText != SelectedContact.Number) + { + Contacts.Refresh(); + } + } + } + } + + private bool DropDownFilter(object item) + { + var contact = item as Contact; + if (contact == null) return false; + + // No filter + if (string.IsNullOrEmpty(SearchText)) return true; + // + if (contact.Name.ToLower().Contains(SearchText.ToLower())) + { + return true; + } + + if (contact.Company.ToLower().Contains(SearchText.ToLower())) + { + return true; + } + + if (contact.Number.ToLower().Contains(SearchText.ToLower())) + { + return true; + } + + return false; + } + + #endregion ComboBox + + + private void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/Mixpanel.cs b/SipgateFaxdrucker/Mixpanel.cs new file mode 100644 index 0000000..54a6df3 --- /dev/null +++ b/SipgateFaxdrucker/Mixpanel.cs @@ -0,0 +1,107 @@ +using Mixpanel; +using System; +using System.Diagnostics; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; +using SipgateFaxdrucker.Properties; +using SipgateFaxdrucker.SipgateAPI.Models; + +namespace SipgateFaxdrucker +{ + class Mixpanel + { + static readonly HttpClient HttpClient = new HttpClient(); + private readonly UserinfoResponse _userinfo; + private MixpanelClient _mc; + + public Mixpanel(UserinfoResponse userInfo) + { + _userinfo = userInfo; + InitMixpanel(); + } + + private void InitMixpanel() + { + var token = Properties.Settings.Default.MixpanelToken; +#if DEBUG + token = Properties.Settings.Default.MixpanelTokenDebug; +#endif + try + { + MixpanelConfig.Global.ErrorLogFn = LogErrors; + MixpanelConfig.Global.HttpPostFn = CustomPostFn; + + object superProperties = new + { + _userinfo.Product, + _userinfo.Domain, + Admin = _userinfo.IsAdmin, + Testaccount = _userinfo.IsTestAccount, + Client = Settings.Default.MixpanelClient, + VersionNumber = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion, + DistinctId = Utils.CreateSha256Hash($"{_userinfo.MasterSipId}{_userinfo.Sub}"), + account_id = Utils.CreateSha256Hash(_userinfo.MasterSipId), + OS = Environment.OSVersion.VersionString, + Is64Bit= Environment.Is64BitOperatingSystem.ToString(), + }; + + MixpanelConfig config = new MixpanelConfig + { + MixpanelPropertyNameFormat = MixpanelPropertyNameFormat.TitleCase + }; + + _mc = new MixpanelClient(token, config, superProperties); + _mc.PeopleSet(new + { + Product = _userinfo.Product, + ProductDomain = _userinfo.Domain, + Admin = _userinfo.IsAdmin, + Testaccount = _userinfo.IsTestAccount, + }); + + } + catch (Exception e) + { + Utils.LogCritical(e.Message); + } + } + + public async Task TrackPageView(string path) + { + object properties = new + { + PagePath = path + }; + + return await _mc.TrackAsync("View Page", properties); + } + + private bool CustomPostFn(string url, string formData) + { + // necessary workaround to post to the correct host. Not configurable in Mixpanel Config or per parameters + var correctApiHost = url.Replace("api.mixpanel.com", "api-eu.mixpanel.com"); + + return CustomPostFnAsync(correctApiHost, formData).GetAwaiter().GetResult(); + } + + private async Task CustomPostFnAsync(string url, string formData) + { + HttpResponseMessage responseMessage = + await HttpClient.PostAsync(url, new StringContent(formData)).ConfigureAwait(false); + if (!responseMessage.IsSuccessStatusCode) + { + return false; + } + + string responseContent = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); + return responseContent == "1"; + } + + + private void LogErrors(string error, Exception exception) + { + Utils.LogCritical($"{error} - {exception.Message}"); + } + } +} diff --git a/SipgateFaxdrucker/Program.cs b/SipgateFaxdrucker/Program.cs new file mode 100644 index 0000000..a02da47 --- /dev/null +++ b/SipgateFaxdrucker/Program.cs @@ -0,0 +1,49 @@ +using System; +using System.Diagnostics; + +namespace SipgateFaxdrucker +{ + public class Program + { + [STAThread] + public static void Main() + { + AppDomain.CurrentDomain.UnhandledException += Application_UnhandledException; + + Utils.InitializeTraceSource(); + +#if DEBUG + Utils.faxdruckerTraceSource.Switch.Level = SourceLevels.All; +#endif + + Utils.LogInformation("Started Programm"); + + using (SipgateForm sipgateForm = new SipgateForm()) + { + sipgateForm.ShowDialog(); + sipgateForm.Close(); + } + + Utils.LogInformation("Exited Programm"); + Utils.faxdruckerTraceSource.Close(); + } + + + /// + /// All unhandled exceptions will bubble their way up here - + /// a final error dialog will be displayed before the crash and burn + /// + /// pack + /// + static void Application_UnhandledException(object sender, UnhandledExceptionEventArgs uex) + { + Exception exception = uex.ExceptionObject as Exception; + Utils.LogCritical($"Unhandled exception: {uex.ExceptionObject} {exception?.GetType()}"); + Utils.faxdruckerTraceSource.Close(); + + ErrorDialog errorDialog = new ErrorDialog(Utils.faxdruckerTraceSource); + errorDialog.HandleUnhandledException(uex); + + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/Properties/Annotations.cs b/SipgateFaxdrucker/Properties/Annotations.cs new file mode 100644 index 0000000..97d591e --- /dev/null +++ b/SipgateFaxdrucker/Properties/Annotations.cs @@ -0,0 +1,1236 @@ +/* MIT License + +Copyright (c) 2016 JetBrains http://www.jetbrains.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ + +using System; +// ReSharper disable InheritdocConsiderUsage + +#pragma warning disable 1591 +// ReSharper disable UnusedMember.Global +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable IntroduceOptionalParameters.Global +// ReSharper disable MemberCanBeProtected.Global +// ReSharper disable InconsistentNaming + +namespace SipgateFaxdrucker.Annotations +{ + /// + /// Indicates that the value of the marked element could be null sometimes, + /// so checking for null is required before its usage. + /// + /// + /// [CanBeNull] object Test() => null; + /// + /// void UseTest() { + /// var p = Test(); + /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class CanBeNullAttribute : Attribute { } + + /// + /// Indicates that the value of the marked element can never be null. + /// + /// + /// [NotNull] object Foo() { + /// return null; // Warning: Possible 'null' assignment + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class NotNullAttribute : Attribute { } + + /// + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can never be null. + /// + /// + /// public void Foo([ItemNotNull]List<string> books) + /// { + /// foreach (var book in books) { + /// if (book != null) // Warning: Expression is always true + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemNotNullAttribute : Attribute { } + + /// + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can be null. + /// + /// + /// public void Foo([ItemCanBeNull]List<string> books) + /// { + /// foreach (var book in books) + /// { + /// // Warning: Possible 'System.NullReferenceException' + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemCanBeNullAttribute : Attribute { } + + /// + /// Indicates that the marked method builds string by the format pattern and (optional) arguments. + /// The parameter, which contains the format string, should be given in constructor. The format string + /// should be in -like form. + /// + /// + /// [StringFormatMethod("message")] + /// void ShowError(string message, params object[] args) { /* do something */ } + /// + /// void Foo() { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Method | + AttributeTargets.Property | AttributeTargets.Delegate)] + public sealed class StringFormatMethodAttribute : Attribute + { + /// + /// Specifies which parameter of an annotated method should be treated as the format string + /// + public StringFormatMethodAttribute([NotNull] string formatParameterName) + { + FormatParameterName = formatParameterName; + } + + [NotNull] public string FormatParameterName { get; } + } + + /// + /// Use this annotation to specify a type that contains static or const fields + /// with values for the annotated property/field/parameter. + /// The specified type will be used to improve completion suggestions. + /// + /// + /// namespace TestNamespace + /// { + /// public class Constants + /// { + /// public static int INT_CONST = 1; + /// public const string STRING_CONST = "1"; + /// } + /// + /// public class Class1 + /// { + /// [ValueProvider("TestNamespace.Constants")] public int myField; + /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } + /// + /// public void Test() + /// { + /// Foo(/*try completion here*/);// + /// myField = /*try completion here*/ + /// } + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, + AllowMultiple = true)] + public sealed class ValueProviderAttribute : Attribute + { + public ValueProviderAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; } + } + + /// + /// Indicates that the integral value falls into the specified interval. + /// It's allowed to specify multiple non-intersecting intervals. + /// Values of interval boundaries are inclusive. + /// + /// + /// void Foo([ValueRange(0, 100)] int value) { + /// if (value == -1) { // Warning: Expression is always 'false' + /// ... + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | + AttributeTargets.Method | AttributeTargets.Delegate, + AllowMultiple = true)] + public sealed class ValueRangeAttribute : Attribute + { + public object From { get; } + public object To { get; } + + public ValueRangeAttribute(long from, long to) + { + From = from; + To = to; + } + + public ValueRangeAttribute(ulong from, ulong to) + { + From = from; + To = to; + } + + public ValueRangeAttribute(long value) + { + From = To = value; + } + + public ValueRangeAttribute(ulong value) + { + From = To = value; + } + } + + /// + /// Indicates that the integral value never falls below zero. + /// + /// + /// void Foo([NonNegativeValue] int value) { + /// if (value == -1) { // Warning: Expression is always 'false' + /// ... + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | + AttributeTargets.Method | AttributeTargets.Delegate)] + public sealed class NonNegativeValueAttribute : Attribute { } + + /// + /// Indicates that the function argument should be a string literal and match one + /// of the parameters of the caller function. For example, ReSharper annotates + /// the parameter of . + /// + /// + /// void Foo(string param) { + /// if (param == null) + /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol + /// } + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InvokerParameterNameAttribute : Attribute { } + + /// + /// Indicates that the method is contained in a type that implements + /// System.ComponentModel.INotifyPropertyChanged interface and this method + /// is used to notify that some property value changed. + /// + /// + /// The method should be non-static and conform to one of the supported signatures: + /// + /// NotifyChanged(string) + /// NotifyChanged(params string[]) + /// NotifyChanged{T}(Expression{Func{T}}) + /// NotifyChanged{T,U}(Expression{Func{T,U}}) + /// SetProperty{T}(ref T, T, string) + /// + /// + /// + /// public class Foo : INotifyPropertyChanged { + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// [NotifyPropertyChangedInvocator] + /// protected virtual void NotifyChanged(string propertyName) { ... } + /// + /// string _name; + /// + /// public string Name { + /// get { return _name; } + /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } + /// } + /// } + /// + /// Examples of generated notifications: + /// + /// NotifyChanged("Property") + /// NotifyChanged(() => Property) + /// NotifyChanged((VM x) => x.Property) + /// SetProperty(ref myField, value, "Property") + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute + { + public NotifyPropertyChangedInvocatorAttribute() { } + public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) + { + ParameterName = parameterName; + } + + [CanBeNull] public string ParameterName { get; } + } + + /// + /// Describes dependency between method input and output. + /// + /// + ///

Function Definition Table syntax:

+ /// + /// FDT ::= FDTRow [;FDTRow]* + /// FDTRow ::= Input => Output | Output <= Input + /// Input ::= ParameterName: Value [, Input]* + /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} + /// Value ::= true | false | null | notnull | canbenull + /// + /// If the method has a single input parameter, its name could be omitted.
+ /// Using halt (or void/nothing, which is the same) for the method output + /// means that the method doesn't return normally (throws or terminates the process).
+ /// Value canbenull is only applicable for output parameters.
+ /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute + /// with rows separated by semicolon. There is no notion of order rows, all rows are checked + /// for applicability and applied per each program state tracked by the analysis engine.
+ ///
+ /// + /// + /// [ContractAnnotation("=> halt")] + /// public void TerminationMethod() + /// + /// + /// [ContractAnnotation("null <= param:null")] // reverse condition syntax + /// public string GetName(string surname) + /// + /// + /// [ContractAnnotation("s:null => true")] + /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() + /// + /// + /// // A method that returns null if the parameter is null, + /// // and not null if the parameter is not null + /// [ContractAnnotation("null => null; notnull => notnull")] + /// public object Transform(object data) + /// + /// + /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] + /// public bool TryParse(string s, out Person result) + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public sealed class ContractAnnotationAttribute : Attribute + { + public ContractAnnotationAttribute([NotNull] string contract) + : this(contract, false) { } + + public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) + { + Contract = contract; + ForceFullStates = forceFullStates; + } + + [NotNull] public string Contract { get; } + + public bool ForceFullStates { get; } + } + + /// + /// Indicates whether the marked element should be localized. + /// + /// + /// [LocalizationRequiredAttribute(true)] + /// class Foo { + /// string str = "my string"; // Warning: Localizable string + /// } + /// + [AttributeUsage(AttributeTargets.All)] + public sealed class LocalizationRequiredAttribute : Attribute + { + public LocalizationRequiredAttribute() : this(true) { } + + public LocalizationRequiredAttribute(bool required) + { + Required = required; + } + + public bool Required { get; } + } + + /// + /// Indicates that the value of the marked type (or its derivatives) + /// cannot be compared using '==' or '!=' operators and Equals() + /// should be used instead. However, using '==' or '!=' for comparison + /// with null is always permitted. + /// + /// + /// [CannotApplyEqualityOperator] + /// class NoEquality { } + /// + /// class UsesNoEquality { + /// void Test() { + /// var ca1 = new NoEquality(); + /// var ca2 = new NoEquality(); + /// if (ca1 != null) { // OK + /// bool condition = ca1 == ca2; // Warning + /// } + /// } + /// } + /// + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] + public sealed class CannotApplyEqualityOperatorAttribute : Attribute { } + + /// + /// When applied to a target attribute, specifies a requirement for any type marked + /// with the target attribute to implement or inherit specific type or types. + /// + /// + /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement + /// class ComponentAttribute : Attribute { } + /// + /// [Component] // ComponentAttribute requires implementing IComponent interface + /// class MyComponent : IComponent { } + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [BaseTypeRequired(typeof(Attribute))] + public sealed class BaseTypeRequiredAttribute : Attribute + { + public BaseTypeRequiredAttribute([NotNull] Type baseType) + { + BaseType = baseType; + } + + [NotNull] public Type BaseType { get; } + } + + /// + /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), + /// so this symbol will not be reported as unused (as well as by other usage inspections). + /// + [AttributeUsage(AttributeTargets.All)] + public sealed class UsedImplicitlyAttribute : Attribute + { + public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) { } + + public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) { } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + public ImplicitUseKindFlags UseKindFlags { get; } + + public ImplicitUseTargetFlags TargetFlags { get; } + } + + /// + /// Can be applied to attributes, type parameters, and parameters of a type assignable from . + /// When applied to an attribute, the decorated attribute behaves the same as . + /// When applied to a type parameter or to a parameter of type , indicates that the corresponding type + /// is used implicitly. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] + public sealed class MeansImplicitUseAttribute : Attribute + { + public MeansImplicitUseAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) { } + + public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) { } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } + + [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } + } + + /// + /// Specify the details of implicitly used symbol when it is marked + /// with or . + /// + [Flags] + public enum ImplicitUseKindFlags + { + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + /// Only entity marked with attribute considered used. + Access = 1, + /// Indicates implicit assignment to a member. + Assign = 2, + /// + /// Indicates implicit instantiation of a type with fixed constructor signature. + /// That means any unused constructor parameters won't be reported as such. + /// + InstantiatedWithFixedConstructorSignature = 4, + /// Indicates implicit instantiation of a type. + InstantiatedNoFixedConstructorSignature = 8, + } + + /// + /// Specify what is considered to be used implicitly when marked + /// with or . + /// + [Flags] + public enum ImplicitUseTargetFlags + { + Default = Itself, + Itself = 1, + /// Members of entity marked with attribute are considered used. + Members = 2, + /// Inherited entities are considered used. + WithInheritors = 4, + /// Entity marked with attribute and all its members considered used. + WithMembers = Itself | Members + } + + /// + /// This attribute is intended to mark publicly available API + /// which should not be removed and so is treated as used. + /// + [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] + [AttributeUsage(AttributeTargets.All, Inherited = false)] + public sealed class PublicAPIAttribute : Attribute + { + public PublicAPIAttribute() { } + + public PublicAPIAttribute([NotNull] string comment) + { + Comment = comment; + } + + [CanBeNull] public string Comment { get; } + } + + /// + /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. + /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. + /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InstantHandleAttribute : Attribute { } + + /// + /// Indicates that a method does not make any observable state changes. + /// The same as System.Diagnostics.Contracts.PureAttribute. + /// + /// + /// [Pure] int Multiply(int x, int y) => x * y; + /// + /// void M() { + /// Multiply(123, 42); // Warning: Return value of pure method is not used + /// } + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class PureAttribute : Attribute { } + + /// + /// Indicates that the return value of the method invocation must be used. + /// + /// + /// Methods decorated with this attribute (in contrast to pure methods) might change state, + /// but make no sense without using their return value.
+ /// Similarly to , this attribute + /// will help detecting usages of the method when the return value in not used. + /// Additionally, you can optionally specify a custom message, which will be used when showing warnings, e.g. + /// [MustUseReturnValue("Use the return value to...")]. + ///
+ [AttributeUsage(AttributeTargets.Method)] + public sealed class MustUseReturnValueAttribute : Attribute + { + public MustUseReturnValueAttribute() { } + + public MustUseReturnValueAttribute([NotNull] string justification) + { + Justification = justification; + } + + [CanBeNull] public string Justification { get; } + } + + /// + /// Indicates the type member or parameter of some type, that should be used instead of all other ways + /// to get the value of that type. This annotation is useful when you have some "context" value evaluated + /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. + /// + /// + /// class Foo { + /// [ProvidesContext] IBarService _barService = ...; + /// + /// void ProcessNode(INode node) { + /// DoSomething(node, node.GetGlobalServices().Bar); + /// // ^ Warning: use value of '_barService' field + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] + public sealed class ProvidesContextAttribute : Attribute { } + + /// + /// Indicates that a parameter is a path to a file or a folder within a web project. + /// Path can be relative or absolute, starting from web root (~). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class PathReferenceAttribute : Attribute + { + public PathReferenceAttribute() { } + + public PathReferenceAttribute([NotNull, PathReference] string basePath) + { + BasePath = basePath; + } + + [CanBeNull] public string BasePath { get; } + } + + /// + /// An extension method marked with this attribute is processed by code completion + /// as a 'Source Template'. When the extension method is completed over some expression, its source code + /// is automatically expanded like a template at call site. + /// + /// + /// Template method body can contain valid source code and/or special comments starting with '$'. + /// Text inside these comments is added as source code when the template is applied. Template parameters + /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. + /// Use the attribute to specify macros for parameters. + /// + /// + /// In this example, the 'forEach' method is a source template available over all values + /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: + /// + /// [SourceTemplate] + /// public static void forEach<T>(this IEnumerable<T> xs) { + /// foreach (var x in xs) { + /// //$ $END$ + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class SourceTemplateAttribute : Attribute { } + + /// + /// Allows specifying a macro for a parameter of a source template. + /// + /// + /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression + /// is defined in the property. When applied on a method, the target + /// template parameter is defined in the property. To apply the macro silently + /// for the parameter, set the property value = -1. + /// + /// + /// Applying the attribute on a source template method: + /// + /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] + /// public static void forEach<T>(this IEnumerable<T> collection) { + /// foreach (var item in collection) { + /// //$ $END$ + /// } + /// } + /// + /// Applying the attribute on a template method parameter: + /// + /// [SourceTemplate] + /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { + /// /*$ var $x$Id = "$newguid$" + x.ToString(); + /// x.DoSomething($x$Id); */ + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] + public sealed class MacroAttribute : Attribute + { + /// + /// Allows specifying a macro that will be executed for a source template + /// parameter when the template is expanded. + /// + [CanBeNull] public string Expression { get; set; } + + /// + /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// + /// + /// If the target parameter is used several times in the template, only one occurrence becomes editable; + /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, + /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// + public int Editable { get; set; } + + /// + /// Identifies the target parameter of a source template if the + /// is applied on a template method. + /// + [CanBeNull] public string Target { get; set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute + { + public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute + { + public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute + { + public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcMasterLocationFormatAttribute : Attribute + { + public AspMvcMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute + { + public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcViewLocationFormatAttribute : Attribute + { + public AspMvcViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC action. If applied to a method, the MVC action name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcActionAttribute : Attribute + { + public AspMvcActionAttribute() { } + + public AspMvcActionAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcAreaAttribute : Attribute + { + public AspMvcAreaAttribute() { } + + public AspMvcAreaAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is + /// an MVC controller. If applied to a method, the MVC controller name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcControllerAttribute : Attribute + { + public AspMvcControllerAttribute() { } + + public AspMvcControllerAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcMasterAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcModelTypeAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC + /// partial view. If applied to a method, the MVC partial view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcPartialViewAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public sealed class AspMvcSuppressViewErrorAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcDisplayTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcEditorTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. + /// Use this attribute for custom wrappers similar to + /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Controller.View(Object). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component name. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewComponentAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component view. If applied to a method, the MVC view component view name is default. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class AspMvcViewComponentViewAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. When applied to a parameter of an attribute, + /// indicates that this parameter is an MVC action name. + /// + /// + /// [ActionName("Foo")] + /// public ActionResult Login(string returnUrl) { + /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK + /// return RedirectToAction("Bar"); // Error: Cannot resolve action + /// } + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] + public sealed class AspMvcActionSelectorAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] + public sealed class HtmlElementAttributesAttribute : Attribute + { + public HtmlElementAttributesAttribute() { } + + public HtmlElementAttributesAttribute([NotNull] string name) + { + Name = name; + } + + [CanBeNull] public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class HtmlAttributeValueAttribute : Attribute + { + public HtmlAttributeValueAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; } + } + + /// + /// Razor attribute. Indicates that the marked parameter or method is a Razor section. + /// Use this attribute for custom wrappers similar to + /// System.Web.WebPages.WebPageBase.RenderSection(String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class RazorSectionAttribute : Attribute { } + + /// + /// Indicates how method, constructor invocation, or property access + /// over collection type affects the contents of the collection. + /// Use to specify the access type. + /// + /// + /// Using this attribute only makes sense if all collection methods are marked with this attribute. + /// + /// + /// public class MyStringCollection : List<string> + /// { + /// [CollectionAccess(CollectionAccessType.Read)] + /// public string GetFirstString() + /// { + /// return this.ElementAt(0); + /// } + /// } + /// class Test + /// { + /// public void Foo() + /// { + /// // Warning: Contents of the collection is never updated + /// var col = new MyStringCollection(); + /// string x = col.GetFirstString(); + /// } + /// } + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] + public sealed class CollectionAccessAttribute : Attribute + { + public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + { + CollectionAccessType = collectionAccessType; + } + + public CollectionAccessType CollectionAccessType { get; } + } + + /// + /// Provides a value for the to define + /// how the collection method invocation affects the contents of the collection. + /// + [Flags] + public enum CollectionAccessType + { + /// Method does not use or modify content of the collection. + None = 0, + /// Method only reads content of the collection but does not modify it. + Read = 1, + /// Method can change content of the collection but does not add new elements. + ModifyExistingContent = 2, + /// Method can add new elements to the collection. + UpdatedContent = ModifyExistingContent | 4 + } + + /// + /// Indicates that the marked method is assertion method, i.e. it halts the control flow if + /// one of the conditions is satisfied. To set the condition, mark one of the parameters with + /// attribute. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class AssertionMethodAttribute : Attribute { } + + /// + /// Indicates the condition parameter of the assertion method. The method itself should be + /// marked by attribute. The mandatory argument of + /// the attribute is the assertion type. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AssertionConditionAttribute : Attribute + { + public AssertionConditionAttribute(AssertionConditionType conditionType) + { + ConditionType = conditionType; + } + + public AssertionConditionType ConditionType { get; } + } + + /// + /// Specifies assertion type. If the assertion method argument satisfies the condition, + /// then the execution continues. Otherwise, execution is assumed to be halted. + /// + public enum AssertionConditionType + { + /// Marked parameter should be evaluated to true. + IS_TRUE = 0, + /// Marked parameter should be evaluated to false. + IS_FALSE = 1, + /// Marked parameter should be evaluated to null value. + IS_NULL = 2, + /// Marked parameter should be evaluated to not null value. + IS_NOT_NULL = 3, + } + + /// + /// Indicates that the marked method unconditionally terminates control flow execution. + /// For example, it could unconditionally throw exception. + /// + [Obsolete("Use [ContractAnnotation('=> halt')] instead")] + [AttributeUsage(AttributeTargets.Method)] + public sealed class TerminatesProgramAttribute : Attribute { } + + /// + /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, + /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters + /// of delegate type by analyzing LINQ method chains. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class LinqTunnelAttribute : Attribute { } + + /// + /// Indicates that IEnumerable passed as a parameter is not enumerated. + /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. + /// + /// + /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class + /// { + /// // custom check for null but no enumeration + /// } + /// + /// void Foo(IEnumerable<string> values) + /// { + /// ThrowIfNull(values, nameof(values)); + /// var x = values.ToList(); // No warnings about multiple enumeration + /// } + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class NoEnumerationAttribute : Attribute { } + + /// + /// Indicates that the marked parameter is a regular expression pattern. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class RegexPatternAttribute : Attribute { } + + /// + /// Prevents the Member Reordering feature from tossing members of the marked class. + /// + /// + /// The attribute must be mentioned in your member reordering patterns. + /// + [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] + public sealed class NoReorderAttribute : Attribute { } + + /// + /// XAML attribute. Indicates the type that has ItemsSource property and should be treated + /// as ItemsControl-derived type, to enable inner items DataContext type resolve. + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class XamlItemsControlAttribute : Attribute { } + + /// + /// XAML attribute. Indicates the property of some BindingBase-derived type, that + /// is used to bind some item of ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// Property should have the tree ancestor of the ItemsControl type or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + public sealed class XamlItemBindingOfItemsControlAttribute : Attribute { } + + /// + /// XAML attribute. Indicates the property of some Style-derived type, that + /// is used to style items of ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// Property should have the tree ancestor of the ItemsControl type or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + public sealed class XamlItemStyleOfItemsControlAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspChildControlTypeAttribute : Attribute + { + public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + { + TagName = tagName; + ControlType = controlType; + } + + [NotNull] public string TagName { get; } + + [NotNull] public Type ControlType { get; } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldsAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspMethodPropertyAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspRequiredAttributeAttribute : Attribute + { + public AspRequiredAttributeAttribute([NotNull] string attribute) + { + Attribute = attribute; + } + + [NotNull] public string Attribute { get; } + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspTypePropertyAttribute : Attribute + { + public bool CreateConstructorReferences { get; } + + public AspTypePropertyAttribute(bool createConstructorReferences) + { + CreateConstructorReferences = createConstructorReferences; + } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorImportNamespaceAttribute : Attribute + { + public RazorImportNamespaceAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorInjectionAttribute : Attribute + { + public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + { + Type = type; + FieldName = fieldName; + } + + [NotNull] public string Type { get; } + + [NotNull] public string FieldName { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorDirectiveAttribute : Attribute + { + public RazorDirectiveAttribute([NotNull] string directive) + { + Directive = directive; + } + + [NotNull] public string Directive { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorPageBaseTypeAttribute : Attribute + { + public RazorPageBaseTypeAttribute([NotNull] string baseType) + { + BaseType = baseType; + } + public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) + { + BaseType = baseType; + PageName = pageName; + } + + [NotNull] public string BaseType { get; } + [CanBeNull] public string PageName { get; } + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorHelperCommonAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class RazorLayoutAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteLiteralMethodAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteMethodAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RazorWriteMethodParameterAttribute : Attribute { } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/Properties/AssemblyInfo.cs b/SipgateFaxdrucker/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6df4961 --- /dev/null +++ b/SipgateFaxdrucker/Properties/AssemblyInfo.cs @@ -0,0 +1,42 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SipgateFaxdrucker")] +[assembly: AssemblyDescription("Postscript printer output redirector")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] +[assembly: AssemblyVersion("4.3.0.0")] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +//[assembly: AssemblyVersion("1.0.0.0")] +//[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SipgateFaxdrucker/Properties/Resources.Designer.cs b/SipgateFaxdrucker/Properties/Resources.Designer.cs new file mode 100644 index 0000000..4cefdd7 --- /dev/null +++ b/SipgateFaxdrucker/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace SipgateFaxdrucker.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SipgateFaxdrucker.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/SipgateFaxdrucker/Properties/Resources.resx b/SipgateFaxdrucker/Properties/Resources.resx new file mode 100644 index 0000000..2f96abe --- /dev/null +++ b/SipgateFaxdrucker/Properties/Resources.resx @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + \ No newline at end of file diff --git a/SipgateFaxdrucker/Properties/Settings.Designer.cs b/SipgateFaxdrucker/Properties/Settings.Designer.cs new file mode 100644 index 0000000..1f099df --- /dev/null +++ b/SipgateFaxdrucker/Properties/Settings.Designer.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace SipgateFaxdrucker.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://api.sipgate.com")] + public string ApiBaseUrl { + get { + return ((string)(this["ApiBaseUrl"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://login.sipgate.com")] + public string LoginBaseUrl { + get { + return ((string)(this["LoginBaseUrl"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("sipgate_faxdrucker_win")] + public string ClientId { + get { + return ((string)(this["ClientId"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("faxdrucker")] + public string MixpanelClient { + get { + return ((string)(this["MixpanelClient"])); + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("7")] + public string LogFileStorageInDays { + get { + return ((string)(this["LogFileStorageInDays"])); + } + set { + this["LogFileStorageInDays"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://sipgate-faxdrucker.s3.eu-central-1.amazonaws.com/version.xml")] + public string UpdateCheckUrl { + get { + return ((string)(this["UpdateCheckUrl"])); + } + set { + this["UpdateCheckUrl"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("ba6490d191f97adf977a1293a1084b53")] + public string MixpanelToken { + get { + return ((string)(this["MixpanelToken"])); + } + set { + this["MixpanelToken"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("5e2eedfb2db9a53766edab1380f6017e")] + public string MixpanelTokenDebug { + get { + return ((string)(this["MixpanelTokenDebug"])); + } + set { + this["MixpanelTokenDebug"] = value; + } + } + } +} diff --git a/SipgateFaxdrucker/Properties/Settings.settings b/SipgateFaxdrucker/Properties/Settings.settings new file mode 100644 index 0000000..481bfc2 --- /dev/null +++ b/SipgateFaxdrucker/Properties/Settings.settings @@ -0,0 +1,30 @@ + + + + + + https://api.sipgate.com + + + https://login.sipgate.com + + + sipgate_faxdrucker_win + + + faxdrucker + + + 7 + + + https://sipgate-faxdrucker.s3.eu-central-1.amazonaws.com/version.xml + + + ba6490d191f97adf977a1293a1084b53 + + + 5e2eedfb2db9a53766edab1380f6017e + + + \ No newline at end of file diff --git a/SipgateFaxdrucker/RedirectionPage.html b/SipgateFaxdrucker/RedirectionPage.html new file mode 100644 index 0000000..6b41e5f --- /dev/null +++ b/SipgateFaxdrucker/RedirectionPage.html @@ -0,0 +1,48 @@ + + + + + + sipgate Faxdrucker Login + + + + +
+

Sie haben sich erfolgreich angemeldet

+

Ihr sipgate Faxdrucker steht nun für Sie bereit.
Bitte kehren Sie zurück in das Programm.

+
+
+ +
+ + \ No newline at end of file diff --git a/SipgateFaxdrucker/RedirectionPageFailure.html b/SipgateFaxdrucker/RedirectionPageFailure.html new file mode 100644 index 0000000..1d5023c --- /dev/null +++ b/SipgateFaxdrucker/RedirectionPageFailure.html @@ -0,0 +1,55 @@ + + + + + + sipgate Faxdrucker Login + + + + +
+ + + +
+
+

Anmeldung fehlgeschlagen!

+

Die Anmeldung bei Ihrem sipgate Faxdrucker war nicht erfolgreich.
Bitte stellen Sie sicher, dass die benötigten Zugriffsrechte für den Account bestätigt wurden.

+
+ + \ No newline at end of file diff --git a/SipgateFaxdrucker/Resources/Box_Arrow_Up.svg b/SipgateFaxdrucker/Resources/Box_Arrow_Up.svg new file mode 100644 index 0000000..6dcd88d --- /dev/null +++ b/SipgateFaxdrucker/Resources/Box_Arrow_Up.svg @@ -0,0 +1,4 @@ + + + + diff --git a/SipgateFaxdrucker/Resources/favicon.ico b/SipgateFaxdrucker/Resources/favicon.ico new file mode 100644 index 0000000..c1401c8 Binary files /dev/null and b/SipgateFaxdrucker/Resources/favicon.ico differ diff --git a/SipgateFaxdrucker/Resources/fax-icon.svg b/SipgateFaxdrucker/Resources/fax-icon.svg new file mode 100644 index 0000000..9f00842 --- /dev/null +++ b/SipgateFaxdrucker/Resources/fax-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/SipgateFaxdrucker/Resources/faxdrucker.ico b/SipgateFaxdrucker/Resources/faxdrucker.ico new file mode 100644 index 0000000..28e1074 Binary files /dev/null and b/SipgateFaxdrucker/Resources/faxdrucker.ico differ diff --git a/SipgateFaxdrucker/Resources/icon-external-link.svg b/SipgateFaxdrucker/Resources/icon-external-link.svg new file mode 100644 index 0000000..5127f93 --- /dev/null +++ b/SipgateFaxdrucker/Resources/icon-external-link.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/SipgateFaxdrucker/Resources/icon-lock.svg b/SipgateFaxdrucker/Resources/icon-lock.svg new file mode 100644 index 0000000..08b4eed --- /dev/null +++ b/SipgateFaxdrucker/Resources/icon-lock.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/SipgateFaxdrucker/Resources/search.svg b/SipgateFaxdrucker/Resources/search.svg new file mode 100644 index 0000000..096a77b --- /dev/null +++ b/SipgateFaxdrucker/Resources/search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/SipgateFaxdrucker/Resources/swagger_fax.json b/SipgateFaxdrucker/Resources/swagger_fax.json new file mode 100644 index 0000000..1432c1a --- /dev/null +++ b/SipgateFaxdrucker/Resources/swagger_fax.json @@ -0,0 +1,433 @@ +{ + "host": "api.sipgate.com", + "basePath": "/v2", + "swagger": "2.0", + "info": { + "description": "This is the sipgate REST API documentation. We build our applications on this API and we invite you to use it too.", + "title": "sipgate API", + "version": "2.0.0" + }, + "schemes": ["https"], + "paths": { + "/sessions/fax": { + "post": { + "tags": ["sessions"], + "summary": "Send a fax", + "description": "", + "operationId": "sendFax", + "produces": ["application/json"], + "parameters": [ + { + "in": "body", + "name": "body", + "required": false, + "schema": { "$ref": "#/definitions/SendFaxRequest" } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { "$ref": "#/definitions/SendFaxSessionResponse" } + }, + "402": { "description": "Insufficient funds" } + }, + "security": [ + { "oauth2": ["all", "sessions:write", "sessions:fax:write"] } + ] + } + }, + "/authorization/userinfo": { + "get": { + "tags": ["authorization"], + "summary": "Get information about the logged in user", + "description": "", + "operationId": "userinfo", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "token", + "required": false, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { "$ref": "#/definitions/UserinfoResponse" } + }, + "401": { "description": "Invalid token supplied" } + } + } + }, + "/{userId}/faxlines": { + "get": { + "tags": ["faxlines"], + "summary": "List all fax lines", + "description": "", + "operationId": "getUserFaxlines", + "produces": ["application/json"], + "parameters": [ + { + "name": "userId", + "in": "path", + "description": "The unique user identifier", + "required": true, + "type": "string", + "x-example": "w0" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { "$ref": "#/definitions/FaxlinesResponse" } + }, + "403": { "description": "Feature not booked" } + }, + "security": [{ "oauth2": ["all", "faxlines:read"] }] + } + }, + "/history/{entryId}": { + "get": { + "tags": ["history"], + "summary": "Get a specific call, fax, SMS or voicemail", + "description": "", + "operationId": "getHistoryById", + "produces": ["application/json"], + "parameters": [ + { + "name": "entryId", + "in": "path", + "description": "The unique call, fax, sms or voicemail identifier", + "required": true, + "type": "string", + "x-example": "abc123" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { "$ref": "#/definitions/HistoryEntryResponse" } + } + }, + "security": [{ "oauth2": ["all", "history:read"] }] + } + }, + "/groupfaxlines": { + "get": { + "tags": ["groups"], + "summary": "List all group fax lines", + "description": "", + "operationId": "getGroupFaxlinesForUser", + "produces": ["application/json"], + "parameters": [ + { + "name": "userId", + "in": "query", + "description": "The unique user identifier", + "required": false, + "type": "string", + "x-example": "w0" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { "$ref": "#/definitions/GroupFaxlinesResponse" } + } + }, + "security": [ + { "oauth2": ["all", "groups:read", "groups:faxlines:read"] } + ] + } + } + }, + "definitions": { + "FaxlineResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "f0" + }, + "alias": { + "type": "string", + "example": "Alexander Bain's fax" + }, + "tagline": { + "type": "string", + "example": "Example Ltd." + }, + "canSend": { + "type": "boolean", + "default": false + }, + "canReceive": { + "type": "boolean", + "default": false + } + } + }, + "FaxlinesResponse": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { "$ref": "#/definitions/FaxlineResponse" } + } + } + }, + "SendFaxRequest": { + "type": "object", + "required": ["base64Content", "faxlineId", "filename", "recipient"], + "properties": { + "faxlineId": { + "type": "string", + "example": "f0" + }, + "recipient": { + "type": "string", + "example": "+4921112345678" + }, + "filename": { + "type": "string", + "example": "fax.pdf" + }, + "base64Content": { + "type": "string", + "example": "TWF5IHRoZSBmb3VydGggYmUgd2l0aCB5b3U=", + "minLength": 0, + "maxLength": 28330000 + } + } + }, + "SendFaxSessionResponse": { + "type": "object", + "properties": { "sessionId": { "type": "string" } } + }, + "UserinfoResponse": { + "type": "object", + "properties": { + "sub": { + "type": "string", + "example": "w0" + }, + "domain": { + "type": "string", + "example": "sipgate.de" + }, + "masterSipId": { + "type": "string", + "example": "0000000" + }, + "locale": { + "type": "string", + "example": "de_DE" + } + } + }, + "HistoryEntryResponse": { + "type": "object", + "properties": { + "id": { "type": "string", "example": "100001234" }, + "source": { "type": "string", "example": "anonymous" }, + "target": { "type": "string", "example": "01579-9912345" }, + "sourceAlias": { "type": "string", "example": "Dennis Ritchie" }, + "targetAlias": { "type": "string", "example": "Ken Thompson" }, + "type": { "type": "string", "enum": ["CALL", "VOICEMAIL", "SMS", "FAX"] }, + "created": { "type": "string", "example": "2016-02-10T14:19:39Z" }, + "lastModified": { "type": "string", "example": "2016-02-10T14:19:39Z" }, + "direction": { + "type": "string", + "enum": ["INCOMING", "OUTGOING", "MISSED_INCOMING", "MISSED_OUTGOING"] + }, + "incoming": { "type": "boolean", "default": false }, + "status": { + "type": "string", + "enum": ["NOPICKUP", "BUSY", "PICKUP", "FORWARD"] + }, + "connectionIds": { "type": "array", "items": { "type": "string" } }, + "read": { "type": "boolean", "example": true, "default": false }, + "archived": { "type": "boolean", "default": false }, + "note": { "type": "string" }, + "endpoints": { + "type": "array", + "items": { "$ref": "#/definitions/RoutedEndpointResponse" } + }, + "starred": { "type": "boolean", "default": false }, + "labels": { + "type": "array", + "uniqueItems": true, + "items": { "type": "string" } + } + } + }, + "RoutedEndpointResponse": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["FORWARDED", "ROUTED", "PICKUP"] }, + "endpoint": { "$ref": "#/definitions/EndpointResponse" } + } + }, + "EndpointResponse": { + "type": "object", + "properties": { + "extension": { "type": "string", "example": "e0" }, + "type": { + "type": "string", + "enum": [ + "SMS", + "REGISTER", + "EXTERNAL", + "FAX", + "MOBILE", + "GROUP", + "VOICEMAIL", + "PHONELINE", + "USER" + ] + } + } + }, + "GroupFaxlineResponse": { + "type": "object", + "properties": { + "id": { "type": "string", "example": "f0" }, + "alias": { "type": "string", "example": "Alexander Bain's fax" }, + "tagline": { "type": "string", "example": "Example Ltd." }, + "canSend": { "type": "boolean", "default": false }, + "canReceive": { "type": "boolean", "default": false }, + "groupId": { "type": "string", "example": "f0" } + } + }, + "GroupFaxlinesResponse": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { "$ref": "#/definitions/GroupFaxlineResponse" } + } + } + } + }, + "securityDefinitions": { + "oauth2": { + "authorizationUrl": "https://login.sipgate.com/auth/realms/third-party/protocol/openid-connect/auth", + "flow": "implicit", + "scopes": { + "account:read": "Access account details", + "account:write": "Manage account details", + "addresses:read": "Access addresses", + "addresses:write": "Manage addresses", + "authorization:oauth2:clients:read": "Access OAuth 2.0 clients", + "authorization:oauth2:clients:write": "Manage OAuth 2.0 clients", + "authorization:oauth:clients:read": "Access OAuth clients", + "authorization:oauth:clients:write": "Manage OAuth clients", + "autorecording:greeting:read": "Access autorecording greeting", + "autorecording:greeting:write": "Manage autorecording greeting", + "balance:read": "Access account balance", + "blacklist:read": "Access blacklist", + "blacklist:write": "Manage blacklist", + "callrestrictions:read": "Access call restrictions", + "callrestrictions:write": "Manage call restrictions", + "contacts:read": "Access contacts", + "contacts:write": "Manage contacts", + "contracts:crm:read": "Access your CRM contracts", + "contracts:read": "Access contracts", + "contracts:write": "Manage contracts", + "devices:callerid:read": "Access caller ID", + "devices:callerid:write": "Manage caller ID", + "devices:contingents:read": "Access mobile device contingents", + "devices:forwardings:read": "Access forwardings of a device", + "devices:forwardings:write": "Manage forwardings of a device", + "devices:localprefix:read": "Access automatic local area code", + "devices:localprefix:write": "Manage automatic local area code", + "devices:read": "Access device settings", + "devices:sim:read": "Access SIM settings", + "devices:sim:write": "Manage SIM settings", + "devices:sims:orders:write": "Order SIM cards", + "devices:singlerowdisplay:read": "Access hide own number settings", + "devices:singlerowdisplay:write": "Manage hide own number settings", + "devices:tariffannouncement:read": "Access rate announcement settings", + "devices:tariffannouncement:write": "Manage rate announcement settings", + "devices:write": "Manage device settings", + "events:read": "Access call events", + "events:write": "Manage call events", + "faxlines:numbers:read": "Access fax device settings (numbers)", + "faxlines:read": "Access fax device settings", + "faxlines:write": "Manage fax device settings", + "groups:devices:write": "Manage group device settings", + "groups:faxlines:read": "Access group fax device settings", + "groups:forwardings:read": "Access forwardings of a group", + "groups:forwardings:write": "Manage forwardings of a group", + "groups:numbers:read": "Access group numbers", + "groups:read": "Access groups", + "groups:users:read": "Access group members", + "groups:voicemails:read": "Access group voicemail settings", + "groups:write": "Manage groups", + "history:read": "Access call history", + "history:write": "Manage call history", + "labels:read": "Access user labels", + "labels:write": "Manage user labels", + "log:webhooks:read": "Read your webhooks log data", + "notifications:read": "Access notifications", + "notifications:write": "Manage notifications", + "numbers:read": "Access phone numbers", + "numbers:write": "Manage phone numbers", + "openid": "User information", + "payment:methods:read": "Access payment methods", + "payment:methods:write": "Manage payment methods", + "phonelines:blockanonymous:read": "Access anonymous call settings", + "phonelines:blockanonymous:write": "Manage anonymous call settings", + "phonelines:busyonbusy:read": "Access busy on busy settings", + "phonelines:busyonbusy:write": "Manage busy on busy settings", + "phonelines:devices:read": "Access connection devices", + "phonelines:devices:write": "Manage connection devices", + "phonelines:forwardings:read": "Access call forwarding settings", + "phonelines:forwardings:write": "Manage call forwarding settings", + "phonelines:numbers:read": "Access connection numbers", + "phonelines:parallelforwardings:read": "Access parallel forwarding settings", + "phonelines:parallelforwardings:write": "Manage parallel forwarding settings", + "phonelines:read": "Access connections", + "phonelines:sipgateio:log:read": "Access webhook debug log", + "phonelines:sipgateio:read": "Access webhooks", + "phonelines:sipgateio:write": "Manage webhooks", + "phonelines:voicemails:greetings:read": "Access connection voicemail announcement settings", + "phonelines:voicemails:greetings:write": "Manage connection voicemail announcement settings", + "phonelines:voicemails:read": "Access connection voicemail settings", + "phonelines:voicemails:write": "Manage connection voicemail settings", + "phonelines:write": "Manage connections", + "phones:read": "Access provisioned phones", + "phones:write": "Manage provisioned phones", + "portings:read": "Access number ports", + "portings:write": "Manage number ports", + "products:read": "Access products", + "push_device:register": "Manage push notifications", + "rtcm:read": "Access active calls", + "rtcm:write": "Manage active calls", + "sessions:calls:write": "Initiate calls", + "sessions:fax:write": "Send faxes", + "sessions:sms:write": "Send SMS", + "sessions:write": "Initiate calls, send faxes, send SMS", + "settings:read": "Access global account settings", + "settings:sipgateio:read": "Access global webhooks", + "settings:sipgateio:write": "Manage global webhooks", + "settings:write": "Manage global account settings", + "sms:callerid:read": "Access SMS caller ID", + "sms:callerid:write": "Manage SMS caller ID", + "sms:read": "Access SMS device settings", + "sms:write": "Manage SMS device settings", + "tacs:read": "List TACs and their texts", + "trunk:read": "Access Trunking settings", + "users:busyonbusy:write": "Manage busy on busy settings", + "users:defaultdevice:write": "Manage default device settings", + "users:read": "Access users", + "users:role:write": "Manage user roles", + "users:write": "Manage users", + "voicemails:read": "Access Voicemails" + }, + "tokenUrl": "https://api.sipgate.com/login/third-party/protocol/openid-connect/token", + "type": "oauth2" + } + } +} diff --git a/SipgateFaxdrucker/SimpleDelegateCommand.cs b/SipgateFaxdrucker/SimpleDelegateCommand.cs new file mode 100644 index 0000000..d2b02db --- /dev/null +++ b/SipgateFaxdrucker/SimpleDelegateCommand.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace SipgateFaxdrucker +{ + public class SimpleDelegateCommand : ICommand + { + // Specify the keys and mouse actions that invoke the command. + public Key GestureKey { get; set; } + public ModifierKeys GestureModifier { get; set; } + public MouseAction MouseGesture { get; set; } + + Action _executeDelegate; + + public SimpleDelegateCommand(Action executeDelegate) + { + _executeDelegate = executeDelegate; + } + + public void Execute(object parameter) + { + _executeDelegate(parameter); + } + + public bool CanExecute(object parameter) { return true; } + public event EventHandler CanExecuteChanged; + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/ISipgateAPI.cs b/SipgateFaxdrucker/SipgateAPI/ISipgateAPI.cs new file mode 100644 index 0000000..4f69e3d --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/ISipgateAPI.cs @@ -0,0 +1,133 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Rest; +using Newtonsoft.Json; +using SipgateFaxdrucker.SipgateAPI.Models; + +namespace SipgateFaxdrucker.SipgateAPI +{ + /// + /// This is the sipgate REST API documentation. We build our applications + /// on this API and we invite you to use it too. + /// + public partial interface ISipgateApi : IDisposable + { + /// + /// The base URI of the service. + /// + Uri BaseUri { get; set; } + + /// + /// Gets or sets json serialization settings. + /// + JsonSerializerSettings SerializationSettings { get; } + + /// + /// Gets or sets json deserialization settings. + /// + JsonSerializerSettings DeserializationSettings { get; } + + /// + /// Subscription credentials which uniquely identify client + /// subscription. + /// + ServiceClientCredentials Credentials { get; } + + + /// + /// Send a fax + /// + /// + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + Task> SendFaxWithHttpMessagesAsync(SendFaxRequest body = default, Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + + /// + /// Get information about the logged in user + /// + /// + /// token + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + Task> UserinfoWithHttpMessagesAsync(string authorization = default, Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + + /// + /// List all fax lines + /// + /// + /// The unique user identifier + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + Task> GetUserFaxlinesWithHttpMessagesAsync(string userId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + + /// + /// Get a specific call, fax, SMS or voicemail + /// + /// + /// The unique call, fax, sms or voicemail identifier + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + Task> GetHistoryByIdWithHttpMessagesAsync(string entryId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + + /// + /// List all group fax lines + /// + /// + /// The unique user identifier + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + Task> GetGroupFaxlinesForUserWithHttpMessagesAsync(string userId = default, Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + + /// + /// List all fax lines + /// + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + Task> GetContactsWithHttpMessagesAsync(int? limit, int? offset, Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + + /// + /// Get balance of account + /// + /// + /// + /// + Task> BalanceWithHttpMessagesAsync(Dictionary> customHeaders = null, CancellationToken cancellationToken = default); + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/AddressResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/AddressResponse.cs new file mode 100644 index 0000000..60d8d90 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/AddressResponse.cs @@ -0,0 +1,89 @@ +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models { + + /// + /// + /// + [DataContract] + public class AddressResponse { + /// + /// Gets or Sets PoBox + /// + [DataMember(Name="poBox", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "poBox")] + public string PoBox { get; set; } + + /// + /// Gets or Sets ExtendedAddress + /// + [DataMember(Name="extendedAddress", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "extendedAddress")] + public string ExtendedAddress { get; set; } + + /// + /// Gets or Sets StreetAddress + /// + [DataMember(Name="streetAddress", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "streetAddress")] + public string StreetAddress { get; set; } + + /// + /// Gets or Sets Locality + /// + [DataMember(Name="locality", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "locality")] + public string Locality { get; set; } + + /// + /// Gets or Sets Region + /// + [DataMember(Name="region", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "region")] + public string Region { get; set; } + + /// + /// Gets or Sets PostalCode + /// + [DataMember(Name="postalCode", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "postalCode")] + public string PostalCode { get; set; } + + /// + /// Gets or Sets Country + /// + [DataMember(Name="country", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "country")] + public string Country { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() { + var sb = new StringBuilder(); + sb.Append("class AddressResponse {\n"); + sb.Append(" PoBox: ").Append(PoBox).Append("\n"); + sb.Append(" ExtendedAddress: ").Append(ExtendedAddress).Append("\n"); + sb.Append(" StreetAddress: ").Append(StreetAddress).Append("\n"); + sb.Append(" Locality: ").Append(Locality).Append("\n"); + sb.Append(" Region: ").Append(Region).Append("\n"); + sb.Append(" PostalCode: ").Append(PostalCode).Append("\n"); + sb.Append(" Country: ").Append(Country).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/BalanceResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/BalanceResponse.cs new file mode 100644 index 0000000..ba5343c --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/BalanceResponse.cs @@ -0,0 +1,49 @@ +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + [DataContract] + public partial class BalanceResponse + { + /// + /// Gets or Sets Amount + /// + [DataMember(Name = "amount", EmitDefaultValue = false)] + [JsonProperty(PropertyName = "amount")] + public int? Amount { get; set; } + + /// + /// Gets or Sets Currency + /// + [DataMember(Name = "currency", EmitDefaultValue = false)] + [JsonProperty(PropertyName = "currency")] + public string Currency { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class BalanceResponse {\n"); + sb.Append(" Amount: ").Append(Amount).Append("\n"); + sb.Append(" Currency: ").Append(Currency).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/ContactResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/ContactResponse.cs new file mode 100644 index 0000000..77ae713 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/ContactResponse.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models { + + /// + /// + /// + [DataContract] + public class ContactResponse { + /// + /// Gets or Sets Id + /// + [DataMember(Name="id", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "id")] + public string Id { get; set; } + + /// + /// Gets or Sets Name + /// + [DataMember(Name="name", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + + /// + /// Gets or Sets Picture + /// + [DataMember(Name="picture", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "picture")] + public string Picture { get; set; } + + /// + /// Gets or Sets Emails + /// + [DataMember(Name="emails", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "emails")] + public List Emails { get; set; } + + /// + /// Gets or Sets Numbers + /// + [DataMember(Name="numbers", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "numbers")] + public List Numbers { get; set; } + + /// + /// Gets or Sets Addresses + /// + [DataMember(Name="addresses", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "addresses")] + public List Addresses { get; set; } + + /// + /// Gets or Sets Organization + /// + [DataMember(Name="organization", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "organization")] + public List> Organization { get; set; } + + /// + /// Gets or Sets Scope + /// + [DataMember(Name="scope", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "scope")] + public string Scope { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() { + var sb = new StringBuilder(); + sb.Append("class ContactResponse {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append(" Picture: ").Append(Picture).Append("\n"); + sb.Append(" Emails: ").Append(Emails).Append("\n"); + sb.Append(" Numbers: ").Append(Numbers).Append("\n"); + sb.Append(" Addresses: ").Append(Addresses).Append("\n"); + sb.Append(" Organization: ").Append(Organization).Append("\n"); + sb.Append(" Scope: ").Append(Scope).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/ContactsResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/ContactsResponse.cs new file mode 100644 index 0000000..b9babf3 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/ContactsResponse.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models { + + /// + /// + /// + [DataContract] + public class ContactsResponse { + /// + /// Gets or Sets Items + /// + [DataMember(Name="items", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "items")] + public List Items { get; set; } + + /// + /// Gets or Sets TotalCount + /// + [DataMember(Name="totalCount", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "totalCount")] + public int? TotalCount { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() { + var sb = new StringBuilder(); + sb.Append("class ContactsResponse {\n"); + sb.Append(" Items: ").Append(Items).Append("\n"); + sb.Append(" TotalCount: ").Append(TotalCount).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/EMailResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/EMailResponse.cs new file mode 100644 index 0000000..810540d --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/EMailResponse.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models { + + /// + /// + /// + [DataContract] + public class EMailResponse { + /// + /// Gets or Sets Email + /// + [DataMember(Name="email", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "email")] + public string Email { get; set; } + + /// + /// Gets or Sets Type + /// + [DataMember(Name="type", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "type")] + public List Type { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() { + var sb = new StringBuilder(); + sb.Append("class EMailResponse {\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" Type: ").Append(Type).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/EndpointResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/EndpointResponse.cs new file mode 100644 index 0000000..67bd5db --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/EndpointResponse.cs @@ -0,0 +1,38 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class EndpointResponse + { + /// + /// Initializes a new instance of the EndpointResponse class. + /// + public EndpointResponse() { } + + /// + /// Initializes a new instance of the EndpointResponse class. + /// + public EndpointResponse(string extension = default, string type = default) + { + Extension = extension; + Type = type; + } + + /// + /// + [JsonProperty(PropertyName = "extension")] + public string Extension { get; set; } + + /// + /// Possible values include: 'SMS', 'REGISTER', 'EXTERNAL', 'FAX', + /// 'MOBILE', 'GROUP', 'VOICEMAIL', 'PHONELINE', 'USER' + /// + [JsonProperty(PropertyName = "type")] + public string Type { get; set; } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/FaxlineResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/FaxlineResponse.cs new file mode 100644 index 0000000..44c0c83 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/FaxlineResponse.cs @@ -0,0 +1,54 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class FaxlineResponse + { + /// + /// Initializes a new instance of the FaxlineResponse class. + /// + public FaxlineResponse() { } + + /// + /// Initializes a new instance of the FaxlineResponse class. + /// + public FaxlineResponse(string id = default, string alias = default, string tagline = default, bool? canSend = default, bool? canReceive = default) + { + Id = id; + Alias = alias; + Tagline = tagline; + CanSend = canSend; + CanReceive = canReceive; + } + + /// + /// + [JsonProperty(PropertyName = "id")] + public string Id { get; set; } + + /// + /// + [JsonProperty(PropertyName = "alias")] + public string Alias { get; set; } + + /// + /// + [JsonProperty(PropertyName = "tagline")] + public string Tagline { get; set; } + + /// + /// + [JsonProperty(PropertyName = "canSend")] + public bool? CanSend { get; set; } + + /// + /// + [JsonProperty(PropertyName = "canReceive")] + public bool? CanReceive { get; set; } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/FaxlinesResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/FaxlinesResponse.cs new file mode 100644 index 0000000..ac45e3e --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/FaxlinesResponse.cs @@ -0,0 +1,31 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class FaxlinesResponse + { + /// + /// Initializes a new instance of the FaxlinesResponse class. + /// + public FaxlinesResponse() { } + + /// + /// Initializes a new instance of the FaxlinesResponse class. + /// + public FaxlinesResponse(IList items = default) + { + Items = items; + } + + /// + /// + [JsonProperty(PropertyName = "items")] + public IList Items { get; set; } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/GroupFaxlineResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/GroupFaxlineResponse.cs new file mode 100644 index 0000000..3df819f --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/GroupFaxlineResponse.cs @@ -0,0 +1,60 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class GroupFaxlineResponse + { + /// + /// Initializes a new instance of the GroupFaxlineResponse class. + /// + public GroupFaxlineResponse() { } + + /// + /// Initializes a new instance of the GroupFaxlineResponse class. + /// + public GroupFaxlineResponse(string id = default, string alias = default, string tagline = default, bool? canSend = default, bool? canReceive = default, string groupId = default) + { + Id = id; + Alias = alias; + Tagline = tagline; + CanSend = canSend; + CanReceive = canReceive; + GroupId = groupId; + } + + /// + /// + [JsonProperty(PropertyName = "id")] + public string Id { get; set; } + + /// + /// + [JsonProperty(PropertyName = "alias")] + public string Alias { get; set; } + + /// + /// + [JsonProperty(PropertyName = "tagline")] + public string Tagline { get; set; } + + /// + /// + [JsonProperty(PropertyName = "canSend")] + public bool? CanSend { get; set; } + + /// + /// + [JsonProperty(PropertyName = "canReceive")] + public bool? CanReceive { get; set; } + + /// + /// + [JsonProperty(PropertyName = "groupId")] + public string GroupId { get; set; } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/GroupFaxlinesResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/GroupFaxlinesResponse.cs new file mode 100644 index 0000000..3150190 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/GroupFaxlinesResponse.cs @@ -0,0 +1,31 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class GroupFaxlinesResponse + { + /// + /// Initializes a new instance of the GroupFaxlinesResponse class. + /// + public GroupFaxlinesResponse() { } + + /// + /// Initializes a new instance of the GroupFaxlinesResponse class. + /// + public GroupFaxlinesResponse(IList items = default) + { + Items = items; + } + + /// + /// + [JsonProperty(PropertyName = "items")] + public IList Items { get; set; } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/HistoryEntryResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/HistoryEntryResponse.cs new file mode 100644 index 0000000..3150881 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/HistoryEntryResponse.cs @@ -0,0 +1,159 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.Rest; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class HistoryEntryResponse + { + /// + /// Initializes a new instance of the HistoryEntryResponse class. + /// + public HistoryEntryResponse() { } + + /// + /// Initializes a new instance of the HistoryEntryResponse class. + /// + public HistoryEntryResponse(string id = default, string source = default, string target = default, string sourceAlias = default, string targetAlias = default, string type = default, string created = default, string lastModified = default, string direction = default, bool? incoming = default, string status = default, IList connectionIds = default, bool? read = default, bool? archived = default, string note = default, IList endpoints = default, bool? starred = default, IList labels = default, string faxStatusType = default) + { + Id = id; + Source = source; + Target = target; + SourceAlias = sourceAlias; + TargetAlias = targetAlias; + Type = type; + Created = created; + LastModified = lastModified; + Direction = direction; + Incoming = incoming; + Status = status; + ConnectionIds = connectionIds; + Read = read; + Archived = archived; + Note = note; + Endpoints = endpoints; + Starred = starred; + Labels = labels; + FaxStatusType = faxStatusType; + } + + /// + /// + [JsonProperty(PropertyName = "id")] + public string Id { get; set; } + + /// + /// + [JsonProperty(PropertyName = "source")] + public string Source { get; set; } + + /// + /// + [JsonProperty(PropertyName = "target")] + public string Target { get; set; } + + /// + /// + [JsonProperty(PropertyName = "sourceAlias")] + public string SourceAlias { get; set; } + + /// + /// + [JsonProperty(PropertyName = "targetAlias")] + public string TargetAlias { get; set; } + + /// + /// Possible values include: 'CALL', 'VOICEMAIL', 'SMS', 'FAX' + /// + [JsonProperty(PropertyName = "type")] + public string Type { get; set; } + + /// + /// + [JsonProperty(PropertyName = "created")] + public string Created { get; set; } + + /// + /// + [JsonProperty(PropertyName = "lastModified")] + public string LastModified { get; set; } + + /// + /// Possible values include: 'INCOMING', 'OUTGOING', + /// 'MISSED_INCOMING', 'MISSED_OUTGOING' + /// + [JsonProperty(PropertyName = "direction")] + public string Direction { get; set; } + + /// + /// + [JsonProperty(PropertyName = "incoming")] + public bool? Incoming { get; set; } + + /// + /// Possible values include: 'NOPICKUP', 'BUSY', 'PICKUP', 'FORWARD' + /// + [JsonProperty(PropertyName = "status")] + public string Status { get; set; } + + /// + /// + [JsonProperty(PropertyName = "connectionIds")] + public IList ConnectionIds { get; set; } + + /// + /// + [JsonProperty(PropertyName = "read")] + public bool? Read { get; set; } + + /// + /// + [JsonProperty(PropertyName = "archived")] + public bool? Archived { get; set; } + + /// + /// + [JsonProperty(PropertyName = "note")] + public string Note { get; set; } + + /// + /// + [JsonProperty(PropertyName = "endpoints")] + public IList Endpoints { get; set; } + + /// + /// + [JsonProperty(PropertyName = "starred")] + public bool? Starred { get; set; } + + /// + /// + [JsonProperty(PropertyName = "labels")] + public IList Labels { get; set; } + + /// + /// Possible values include: 'PENDING', 'SENDING', 'FAILED', 'SENT' + /// + [JsonProperty(PropertyName = "faxStatusType")] + public string FaxStatusType { get; set; } + + /// + /// Validate the object. Throws ValidationException if validation fails. + /// + public virtual void Validate() + { + if (this.Labels != null) + { + if (this.Labels.Count != this.Labels.Distinct().Count()) + { + throw new ValidationException(ValidationRules.UniqueItems, "Labels"); + } + } + } + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/InternalContactResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/InternalContactResponse.cs new file mode 100644 index 0000000..3a3fa15 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/InternalContactResponse.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models { + + /// + /// + /// + [DataContract] + public class InternalContactResponse { + /// + /// Gets or Sets Id + /// + [DataMember(Name="id", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "id")] + public string Id { get; set; } + + /// + /// Gets or Sets Name + /// + [DataMember(Name="name", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + + /// + /// Gets or Sets Emails + /// + [DataMember(Name="emails", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "emails")] + public List Emails { get; set; } + + /// + /// Gets or Sets Mobile + /// + [DataMember(Name="mobile", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "mobile")] + public List Mobile { get; set; } + + /// + /// Gets or Sets Landline + /// + [DataMember(Name="landline", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "landline")] + public List Landline { get; set; } + + /// + /// Gets or Sets Fax + /// + [DataMember(Name="fax", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "fax")] + public List Fax { get; set; } + + /// + /// Gets or Sets Directdial + /// + [DataMember(Name="directdial", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "directdial")] + public List Directdial { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() { + var sb = new StringBuilder(); + sb.Append("class InternalContactResponse {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append(" Emails: ").Append(Emails).Append("\n"); + sb.Append(" Mobile: ").Append(Mobile).Append("\n"); + sb.Append(" Landline: ").Append(Landline).Append("\n"); + sb.Append(" Fax: ").Append(Fax).Append("\n"); + sb.Append(" Directdial: ").Append(Directdial).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/NumberResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/NumberResponse.cs new file mode 100644 index 0000000..e89ae23 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/NumberResponse.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models { + + /// + /// + /// + [DataContract] + public class NumberResponse { + /// + /// Gets or Sets Number + /// + [DataMember(Name="number", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "number")] + public string Number { get; set; } + + /// + /// Gets or Sets Type + /// + [DataMember(Name="type", EmitDefaultValue=false)] + [JsonProperty(PropertyName = "type")] + public List Type { get; set; } + + + /// + /// Get the string presentation of the object + /// + /// String presentation of the object + public override string ToString() { + var sb = new StringBuilder(); + sb.Append("class NumberResponse {\n"); + sb.Append(" Number: ").Append(Number).Append("\n"); + sb.Append(" Type: ").Append(Type).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Get the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + +} +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/RoutedEndpointResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/RoutedEndpointResponse.cs new file mode 100644 index 0000000..bb7631e --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/RoutedEndpointResponse.cs @@ -0,0 +1,37 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class RoutedEndpointResponse + { + /// + /// Initializes a new instance of the RoutedEndpointResponse class. + /// + public RoutedEndpointResponse() { } + + /// + /// Initializes a new instance of the RoutedEndpointResponse class. + /// + public RoutedEndpointResponse(string type = default, EndpointResponse endpoint = default) + { + Type = type; + Endpoint = endpoint; + } + + /// + /// Possible values include: 'FORWARDED', 'ROUTED', 'PICKUP' + /// + [JsonProperty(PropertyName = "type")] + public string Type { get; set; } + + /// + /// + [JsonProperty(PropertyName = "endpoint")] + public EndpointResponse Endpoint { get; set; } + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/SendFaxRequest.cs b/SipgateFaxdrucker/SipgateAPI/Models/SendFaxRequest.cs new file mode 100644 index 0000000..10da35b --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/SendFaxRequest.cs @@ -0,0 +1,87 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Microsoft.Rest; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class SendFaxRequest + { + /// + /// Initializes a new instance of the SendFaxRequest class. + /// + public SendFaxRequest() { } + + /// + /// Initializes a new instance of the SendFaxRequest class. + /// + public SendFaxRequest(string faxlineId, string recipient, string filename, string base64Content) + { + FaxlineId = faxlineId; + Recipient = recipient; + Filename = filename; + Base64Content = base64Content; + } + + /// + /// + [JsonProperty(PropertyName = "faxlineId")] + public string FaxlineId { get; set; } + + /// + /// + [JsonProperty(PropertyName = "recipient")] + public string Recipient { get; set; } + + /// + /// + [JsonProperty(PropertyName = "filename")] + public string Filename { get; set; } + + /// + /// + [JsonProperty(PropertyName = "base64Content")] + public string Base64Content { get; set; } + + /// + /// Validate the object. Throws ValidationException if validation fails. + /// + public virtual void Validate() + { + if (FaxlineId == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "FaxlineId"); + } + if (Recipient == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "Recipient"); + } + if (Filename == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "Filename"); + } + if (Base64Content == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "Base64Content"); + } + if (this.Base64Content != null) + { + if (this.Base64Content.Length > 28330000) + { + throw new ValidationException(ValidationRules.MaxLength, "Base64Content", 28330000); + } + if (this.Base64Content.Length < 0) + { + throw new ValidationException(ValidationRules.MinLength, "Base64Content", 0); + } + } + + } + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/Models/SendFaxSessionResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/SendFaxSessionResponse.cs new file mode 100644 index 0000000..0b284c5 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/SendFaxSessionResponse.cs @@ -0,0 +1,44 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System.Net; +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class SendFaxSessionResponse + { + /// + /// Initializes a new instance of the SendFaxSessionResponse class. + /// + public SendFaxSessionResponse() { } + + /// + /// Initializes a new instance of the SendFaxSessionResponse class. + /// + public SendFaxSessionResponse(string sessionId = default, HttpStatusCode statusCode = default) + { + SessionId = sessionId; + StatusCode = statusCode; + } + + /// + /// Initializes a new instance of the SendFaxSessionResponse class. + /// + public SendFaxSessionResponse(string sessionId = default) + { + SessionId = sessionId; + } + + /// + /// + [JsonProperty(PropertyName = "sessionId")] + public string SessionId { get; set; } + + + /// + [JsonProperty(PropertyName = "statusCode")] + public HttpStatusCode StatusCode { get; set; } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/SipgateAPI/Models/UserinfoResponse.cs b/SipgateFaxdrucker/SipgateAPI/Models/UserinfoResponse.cs new file mode 100644 index 0000000..807998b --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/Models/UserinfoResponse.cs @@ -0,0 +1,68 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using Newtonsoft.Json; + +namespace SipgateFaxdrucker.SipgateAPI.Models +{ + public partial class UserinfoResponse + { + /// + /// Initializes a new instance of the UserinfoResponse class. + /// + public UserinfoResponse() { } + + /// + /// Initializes a new instance of the UserinfoResponse class. + /// + public UserinfoResponse(string sub = default, string domain = default, string masterSipId = default, string locale = default, bool isTestAccount = false, + bool isAdmin = false, + string product = "", + string[] flags = default) + { + Sub = sub; + Domain = domain; + MasterSipId = masterSipId; + Locale = locale; + IsTestAccount = isTestAccount; + IsAdmin = isAdmin; + Product = product; + Flags = flags; + } + + /// + /// + [JsonProperty(PropertyName = "sub")] + public string Sub { get; set; } + + /// + /// + [JsonProperty(PropertyName = "domain")] + public string Domain { get; set; } + + /// + /// + [JsonProperty(PropertyName = "masterSipId")] + public string MasterSipId { get; set; } + + /// + /// + [JsonProperty(PropertyName = "locale")] + public string Locale { get; set; } + + [JsonProperty(PropertyName = "isTestAccount")] + public bool IsTestAccount { get; set; } + + [JsonProperty(PropertyName = "isAdmin")] + public bool IsAdmin { get; set; } + + [JsonProperty(PropertyName = "product")] + public string Product { get; set; } + + [JsonProperty(PropertyName = "flags")] + public string[] Flags { get; set; } + + + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/SipgateAPI.cs b/SipgateFaxdrucker/SipgateAPI/SipgateAPI.cs new file mode 100644 index 0000000..fb3f62e --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/SipgateAPI.cs @@ -0,0 +1,1135 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Rest; +using Microsoft.Rest.Serialization; +using Newtonsoft.Json; +using SipgateFaxdrucker.SipgateAPI.Models; + +namespace SipgateFaxdrucker.SipgateAPI +{ + /// + /// This is the sipgate REST API documentation. We build our applications + /// on this API and we invite you to use it too. + /// + public partial class SipgateApi : ServiceClient, ISipgateApi + { + /// + /// The base URI of the service. + /// + public Uri BaseUri { get; set; } + + /// + /// Gets or sets json serialization settings. + /// + public JsonSerializerSettings SerializationSettings { get; private set; } + + /// + /// Gets or sets json deserialization settings. + /// + public JsonSerializerSettings DeserializationSettings { get; private set; } + + /// + /// Subscription credentials which uniquely identify client subscription. + /// + public ServiceClientCredentials Credentials { get; private set; } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + protected SipgateApi(params DelegatingHandler[] handlers) : base(handlers) + { + Initialize(); + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + protected SipgateApi(HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : base(rootHandler, handlers) + { + Initialize(); + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + protected SipgateApi(Uri baseUri, params DelegatingHandler[] handlers) : this(handlers) + { + if (baseUri == null) + { + throw new ArgumentNullException(nameof(baseUri)); + } + BaseUri = baseUri; + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + protected SipgateApi(Uri baseUri, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers) + { + if (baseUri == null) + { + throw new ArgumentNullException(nameof(baseUri)); + } + BaseUri = baseUri; + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Required. Subscription credentials which uniquely identify client subscription. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + public SipgateApi(ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : this(handlers) + { + Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + if (Credentials != null) + { + Credentials.InitializeServiceClient(this); + } + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Required. Subscription credentials which uniquely identify client subscription. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + public SipgateApi(ServiceClientCredentials credentials, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers) + { + Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + if (Credentials != null) + { + Credentials.InitializeServiceClient(this); + } + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Required. Subscription credentials which uniquely identify client subscription. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + public SipgateApi(Uri baseUri, ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : this(handlers) + { + BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); + Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + + Credentials?.InitializeServiceClient(this); + } + + /// + /// Initializes a new instance of the SipgateAPI class. + /// + /// + /// Optional. The base URI of the service. + /// + /// + /// Required. Subscription credentials which uniquely identify client subscription. + /// + /// + /// Optional. The http client handler used to handle http transport. + /// + /// + /// Optional. The delegating handlers to add to the http client pipeline. + /// + public SipgateApi(Uri baseUri, ServiceClientCredentials credentials, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers) + { + BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); + Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + + Credentials?.InitializeServiceClient(this); + } + + /// + /// An optional partial-method to perform custom initialization. + /// + partial void CustomInitialize(); + /// + /// Initializes client properties. + /// + private void Initialize() + { + BaseUri = new Uri("https://api.sipgate.com/v2"); + SerializationSettings = new JsonSerializerSettings + { + Formatting = Formatting.Indented, + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + ContractResolver = new ReadOnlyJsonContractResolver(), + Converters = new List + { + new Iso8601TimeSpanConverter() + } + }; + DeserializationSettings = new JsonSerializerSettings + { + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + ContractResolver = new ReadOnlyJsonContractResolver(), + Converters = new List + { + new Iso8601TimeSpanConverter() + } + }; + CustomInitialize(); + } + /// + /// Send a fax + /// + /// + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> SendFaxWithHttpMessagesAsync(SendFaxRequest body = default, Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + if (body != null) + { + body.Validate(); + } + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"body", body}, + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "SendFax", tracingParameters); + } + // Construct URL + var baseUrl = BaseUri.AbsoluteUri; + var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "sessions/fax").ToString(); + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("POST"); + httpRequest.RequestUri = new Uri(url); + // Set Headers + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + if (body != null) + { + requestContent = SafeJsonConvert.SerializeObject(body, SerializationSettings); + httpRequest.Content = new StringContent(requestContent, Encoding.UTF8); + httpRequest.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); + } + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent = null; + if ((int)statusCode != 200 && (int)statusCode != 402) + { + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + } + + /// + /// Get information about the logged in user + /// + /// + /// token + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> UserinfoWithHttpMessagesAsync(string authorization = default, Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"authorization", authorization}, + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "Userinfo", tracingParameters); + } + // Construct URL + var baseUrl = BaseUri.AbsoluteUri; + var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "authorization/userinfo").ToString(); + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("GET"); + httpRequest.RequestUri = new Uri(url); + // Set Headers + if (authorization != null) + { + if (httpRequest.Headers.Contains("Authorization")) + { + httpRequest.Headers.Remove("Authorization"); + } + httpRequest.Headers.TryAddWithoutValidation("Authorization", authorization); + } + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent; + if ((int)statusCode != 200 && (int)statusCode != 401) + { + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + } + + /// + /// List all fax lines + /// + /// + /// The unique user identifier + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> GetUserFaxlinesWithHttpMessagesAsync(string userId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + if (userId == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "userId"); + } + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"userId", userId}, + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "GetUserFaxlines", tracingParameters); + } + // Construct URL + var baseUrl = BaseUri.AbsoluteUri; + var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "{userId}/faxlines").ToString(); + url = url.Replace("{userId}", Uri.EscapeDataString(userId)); + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("GET"); + httpRequest.RequestUri = new Uri(url); + // Set Headers + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent; + if ((int)statusCode != 200 && (int)statusCode != 403) + { + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + } + + /// + /// Get a specific call, fax, SMS or voicemail + /// + /// + /// The unique call, fax, sms or voicemail identifier + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> GetHistoryByIdWithHttpMessagesAsync(string entryId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + if (entryId == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "entryId"); + } + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"entryId", entryId}, + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "GetHistoryById", tracingParameters); + } + // Construct URL + var baseUrl = BaseUri.AbsoluteUri; + var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "history/{entryId}").ToString(); + url = url.Replace("{entryId}", Uri.EscapeDataString(entryId)); + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("GET"); + httpRequest.RequestUri = new Uri(url); + // Set Headers + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent = null; + if ((int)statusCode != 200) + { + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + if (httpResponse != null) + { + httpResponse.Dispose(); + } + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + } + + + + + /// + /// List all group fax lines + /// + /// + /// The unique user identifier + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> GetGroupFaxlinesForUserWithHttpMessagesAsync(string userId = default, Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"userId", userId}, + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "GetGroupFaxlinesForUser", tracingParameters); + } + // Construct URL + var baseUrl = BaseUri.AbsoluteUri; + var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "groupfaxlines").ToString(); + List queryParameters = new List(); + if (userId != null) + { + queryParameters.Add($"userId={Uri.EscapeDataString(userId)}"); + } + if (queryParameters.Count > 0) + { + url += "?" + string.Join("&", queryParameters); + } + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("GET"); + httpRequest.RequestUri = new Uri(url); + // Set Headers + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent; + if ((int)statusCode != 200) + { + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + } + // + /// + /// List all fax lines + /// + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> GetContactsWithHttpMessagesAsync(int? limit, int? offset, Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "GetContacts", tracingParameters); + } + // Construct URL + + + var baseUrl = BaseUri.AbsoluteUri; + string url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "contacts").ToString(); + + if (limit.HasValue) + { + url += $"?limit={limit.Value}"; + if (offset.HasValue) + { + url += $"&offset={offset.Value}"; + } + } + else + { + if (offset.HasValue) + { + url += $"?offset={offset.Value}"; + } + } + + + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("GET"); + httpRequest.RequestUri = new Uri(url); + // Set Headers + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent = null; + if ((int)statusCode != 200 && (int)statusCode != 403) + { + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + httpRequest.Dispose(); + if (httpResponse != null) + { + httpResponse.Dispose(); + } + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + } + + public async Task> BalanceWithHttpMessagesAsync(Dictionary> customHeaders = null, CancellationToken cancellationToken = default) + { + + // Tracing + bool shouldTrace = ServiceClientTracing.IsEnabled; + string invocationId = null; + if (shouldTrace) + { + invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary + { + {"cancellationToken", cancellationToken} + }; + ServiceClientTracing.Enter(invocationId, this, "Balance", tracingParameters); + } + // Construct URL + var baseUrl = BaseUri.AbsoluteUri; + var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "balance").ToString(); + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage(); + httpRequest.Method = new HttpMethod("GET"); + httpRequest.RequestUri = new Uri(url); + if (customHeaders != null) + { + foreach (var header in customHeaders) + { + if (httpRequest.Headers.Contains(header.Key)) + { + httpRequest.Headers.Remove(header.Key); + } + httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + // Serialize Request + string requestContent = null; + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (shouldTrace) + { + ServiceClientTracing.SendRequest(invocationId, httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + var httpResponse = await HttpClient + .SendAsync(httpRequest, cancellationToken) + .ConfigureAwait(false); + + if (shouldTrace) + { + ServiceClientTracing.ReceiveResponse(invocationId, httpResponse); + } + HttpStatusCode statusCode = httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string responseContent = null; + if ((int)statusCode != 200 && (int)statusCode != 401) + { + if (statusCode == HttpStatusCode.Forbidden) + { + + throw new NoRightsToFetchBalanceException("Balance endpoint returned 403: Forbidden for this user"); + } + var ex = new HttpOperationException($"Operation returned an invalid status code '{statusCode}'"); + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); + ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); + if (shouldTrace) + { + ServiceClientTracing.Error(invocationId, ex); + } + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw ex; + } + // Create Result + var result = new HttpOperationResponse + { + Request = httpRequest, + Response = httpResponse + }; + // Deserialize Response + if ((int)statusCode == 200) + { + responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + result.Body = SafeJsonConvert.DeserializeObject(responseContent, DeserializationSettings); + } + catch (JsonException ex) + { + httpRequest.Dispose(); + httpResponse.Dispose(); + + throw new SerializationException("Unable to deserialize the response.", responseContent, ex); + } + } + if (shouldTrace) + { + ServiceClientTracing.Exit(invocationId, result); + } + return result; + + } + + + public class NoRightsToFetchBalanceException : Exception + { + public NoRightsToFetchBalanceException() + { + } + + public NoRightsToFetchBalanceException(string message) + : base(message) + { + } + + public NoRightsToFetchBalanceException(string message, Exception inner) + : base(message, inner) + { + } + } + } +} diff --git a/SipgateFaxdrucker/SipgateAPI/SipgateAPIExtensions.cs b/SipgateFaxdrucker/SipgateAPI/SipgateAPIExtensions.cs new file mode 100644 index 0000000..8b88696 --- /dev/null +++ b/SipgateFaxdrucker/SipgateAPI/SipgateAPIExtensions.cs @@ -0,0 +1,244 @@ +// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Rest; +using SipgateFaxdrucker.SipgateAPI.Models; + +namespace SipgateFaxdrucker.SipgateAPI +{ + /// + /// Extension methods for SipgateAPI. + /// + public static partial class SipgateApiExtensions + { + /// + /// Send a fax + /// + /// + /// The operations group for this extension method. + /// + /// + /// + public static SendFaxSessionResponse SendFax(this ISipgateApi operations, SendFaxRequest body = default) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).SendFaxAsync(body), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + /// + /// Send a fax + /// + /// + /// The operations group for this extension method. + /// + /// + /// + /// + /// The cancellation token. + /// + public static async Task SendFaxAsync(this ISipgateApi operations, SendFaxRequest body = default, CancellationToken cancellationToken = default) + { + try + { + using (HttpOperationResponse result = await operations.SendFaxWithHttpMessagesAsync(body, null, cancellationToken).ConfigureAwait(false)) + { + return new SendFaxSessionResponse(result.Body.SessionId, result.Response.StatusCode); + } + } + catch (HttpOperationException hex) + { + return new SendFaxSessionResponse(null, hex.Response.StatusCode); + }catch(Exception exception) + { + Utils.LogCritical("Failed to send fax: " + exception.Message); + return new SendFaxSessionResponse(null,System.Net.HttpStatusCode.InternalServerError); + } + + } + + /// + /// Get information about the logged in user + /// + /// + /// The operations group for this extension method. + /// + /// + /// token + /// + public static UserinfoResponse Userinfo(this ISipgateApi operations, string authorization = default) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).UserinfoAsync(authorization), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + /// + /// Get information about the logged in user + /// + /// + /// The operations group for this extension method. + /// + /// + /// token + /// + /// + /// The cancellation token. + /// + public static async Task UserinfoAsync(this ISipgateApi operations, string authorization = default, CancellationToken cancellationToken = default) + { + using (var result = await operations.UserinfoWithHttpMessagesAsync(authorization, null, cancellationToken).ConfigureAwait(false)) + { + return result.Body; + } + } + + /// + /// List all fax lines + /// + /// + /// The operations group for this extension method. + /// + /// + /// The unique user identifier + /// + public static FaxlinesResponse GetUserFaxlines(this ISipgateApi operations, string userId) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).GetUserFaxlinesAsync(userId), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + /// + /// List all fax lines + /// + /// + /// The operations group for this extension method. + /// + /// + /// The unique user identifier + /// + /// + /// The cancellation token. + /// + public static async Task GetUserFaxlinesAsync(this ISipgateApi operations, string userId, CancellationToken cancellationToken = default) + { + using (var result = await operations.GetUserFaxlinesWithHttpMessagesAsync(userId, null, cancellationToken).ConfigureAwait(false)) + { + return result.Body; + } + } + + /// + /// Get a specific call, fax, SMS or voicemail + /// + /// + /// The operations group for this extension method. + /// + /// + /// The unique call, fax, sms or voicemail identifier + /// + public static HistoryEntryResponse GetHistoryById(this ISipgateApi operations, string entryId) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).GetHistoryByIdAsync(entryId), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + /// + /// Get a specific call, fax, SMS or voicemail + /// + /// + /// The operations group for this extension method. + /// + /// + /// The unique call, fax, sms or voicemail identifier + /// + /// + /// The cancellation token. + /// + public static async Task GetHistoryByIdAsync(this ISipgateApi operations, string entryId, CancellationToken cancellationToken = default) + { + using (var result = await operations.GetHistoryByIdWithHttpMessagesAsync(entryId, null, cancellationToken).ConfigureAwait(false)) + { + return result.Body; + } + } + + /// + /// List all group fax lines + /// + /// + /// The operations group for this extension method. + /// + /// + /// The unique user identifier + /// + public static GroupFaxlinesResponse GetGroupFaxlinesForUser(this ISipgateApi operations, string userId = default) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).GetGroupFaxlinesForUserAsync(userId), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + /// + /// List all group fax lines + /// + /// + /// The operations group for this extension method. + /// + /// + /// The unique user identifier + /// + /// + /// The cancellation token. + /// + public static async Task GetGroupFaxlinesForUserAsync(this ISipgateApi operations, string userId = default, CancellationToken cancellationToken = default) + { + using (var result = await operations.GetGroupFaxlinesForUserWithHttpMessagesAsync(userId, null, cancellationToken).ConfigureAwait(false)) + { + return result.Body; + } + } + + /// + /// List all fax lines + /// + /// + /// The operations group for this extension method. + /// + /// + /// + public static ContactsResponse GetContacts(this ISipgateApi operations, int? limit, int? offset) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).GetContactsAsync(limit, offset), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + /// + /// List all fax lines + /// + /// + /// The operations group for this extension method. + /// + /// + /// + /// The cancellation token. + /// + /// + public static async Task GetContactsAsync(this ISipgateApi operations, int? limit, int? offset, CancellationToken cancellationToken = default) + { + using (var result = await operations.GetContactsWithHttpMessagesAsync(limit, offset, null, cancellationToken).ConfigureAwait(false)) + { + return result.Body; + } + } + + + public static BalanceResponse Balance(this ISipgateApi operations, string authorization = default) + { + return Task.Factory.StartNew(s => ((ISipgateApi)s).BalanceAsync(), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult(); + } + + public static async Task BalanceAsync(this ISipgateApi operations, CancellationToken cancellationToken = default) + { + using (var result = await operations.BalanceWithHttpMessagesAsync(null, cancellationToken).ConfigureAwait(false)) + { + return result.Body; + } + } + } +} diff --git a/SipgateFaxdrucker/SipgateCredentials.cs b/SipgateFaxdrucker/SipgateCredentials.cs new file mode 100644 index 0000000..db02757 --- /dev/null +++ b/SipgateFaxdrucker/SipgateCredentials.cs @@ -0,0 +1,14 @@ +namespace SipgateFaxdrucker +{ + public class SipgateCredentials + { + public string AccessToken { get; } + public string RefreshToken { get; } + + public SipgateCredentials(string accessToken, string refreshToken) + { + AccessToken = accessToken; + RefreshToken = refreshToken; + } + } +} \ No newline at end of file diff --git a/SipgateFaxdrucker/SipgateFaxdrucker.csproj b/SipgateFaxdrucker/SipgateFaxdrucker.csproj new file mode 100644 index 0000000..57f83c9 --- /dev/null +++ b/SipgateFaxdrucker/SipgateFaxdrucker.csproj @@ -0,0 +1,361 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2} + WinExe + Properties + SipgateFaxdrucker + SipgateFaxdrucker + v4.6.1 + + + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + SipgateFaxdrucker.Program + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + false + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + false + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + prompt + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + false + + + app.manifest + + + Resources\faxdrucker.ico + + + + ..\packages\Autoupdater.NET.Official.1.6.4\lib\net45\AutoUpdater.NET.dll + + + ..\packages\DotNetCommonLibrary.4.5.0.5\lib\net40-Client\DotNet Common Library.dll + True + + + ..\packages\DotNetProjects.SVGImage.4.1.92\lib\net46\DotNetProjects.SVGImage.dll + + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.6.9.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll + True + + + ..\packages\Microsoft.IdentityModel.Logging.6.9.0\lib\net461\Microsoft.IdentityModel.Logging.dll + True + + + ..\packages\Microsoft.IdentityModel.Tokens.6.9.0\lib\net461\Microsoft.IdentityModel.Tokens.dll + True + + + ..\packages\Microsoft.Rest.ClientRuntime.2.3.2\lib\net45\Microsoft.Rest.ClientRuntime.dll + + + ..\packages\mixpanel-csharp.5.0.0\lib\net45\Mixpanel.dll + + + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\libphonenumber-csharp.8.12.19\lib\net46\PhoneNumbers.dll + + + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Converters.Wpf.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Core.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Css.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Dom.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Model.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Rendering.Gdi.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Rendering.Wpf.dll + + + ..\packages\SharpVectors.1.7.1\lib\net46\SharpVectors.Runtime.Wpf.dll + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.6.9.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll + True + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + + ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\packages\System.Security.Cryptography.ProtectedData.5.0.0\lib\net461\System.Security.Cryptography.ProtectedData.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + + + + + + + + + + + + + GhostScript\SipgateFaxdruckerSharedAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + SipgateForm.xaml + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + Designer + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + Designer + MSBuild:Compile + + + + + GhostScript\gsdll64.dll + PreserveNewest + + + + + + + + PreserveNewest + + + + + + + + False + Microsoft .NET Framework 4.6.1 %28x86 und x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + {1EAD8E9A-A123-4C37-B31E-AEE1354DF003} + SipgateFaxdruckerCore + + + + + + + + + + \ No newline at end of file diff --git a/SipgateFaxdrucker/SipgateForm.xaml b/SipgateFaxdrucker/SipgateForm.xaml new file mode 100644 index 0000000..448cb09 --- /dev/null +++ b/SipgateFaxdrucker/SipgateForm.xaml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Error + + + + + + Faxanschluss + + + + + + + + + + + + + Faxnummer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +