How can I make a PDF non-printable programmatically using .net?
Short answer. You can't. You can try to set a DRM parameter to prevent printing, but that all depends on the client's software for rendering the PDF and if it respects DRM or no.
Also, assuming you are able to view a PDF there is nothing preventing the user from taking screen captures of the contents presented in the PDF.
Sure you can prevent printing! Of course you cannot prevent a screen capture, but you can definitely prevent a casual user from printing a PDF in the Adobe Reader. I know in our ActiveReports product when we export PDF you can specify various security options that determine whether the user viewing the PDF can print or not. The developer can specify an admin password that can be used to enable only some users to print, while preventing those without the password from printing.
You can read more about this in the PdfSecurity enumeration documentation of ActiveReports. A code sample is in the documentation here. Follow some links on that page to see more information.
If you want to load an existing PDF and modify usually people suggest iTextSharp. Although I have not used it, other people recommend it highly and I think it will work for this read+modify scenario. I managed to find an example of how you can use iTextSharp to enable/disable the "AllowPrint" and other permissions here.
Sounds like you're really looking for a group policy object in Active Directory that prevents users from printing, perhaps?
update
What prevents said users from emailing the PDF to themselves and printing at home, other than another GPO that prevents attachments with given extensions or over certain sizes?
You've got a number of options depending on the full requirement details but the easiest would indeed be to set password encryption on the document. As some of the folks above mentioned, you can set an owner password and user password to encrypt the document. The owner password basically allows admin level access and fully opens up the document to all operations. The user password opens up the document but access is limited to what you specified at the time of encryption, e.g., if you turn turn off printing rights, then someone who supplies the user password won't be able to print the PDF.
We offer a solution that supports .NET and can easily encrypt and also decrypt PDFs. Here's a link to the API docs if you're interested in giving it a look:
http://www.pdfonline.com/easypdf/epsdk_manual/index.htm?page=reference%2Fpdfprocessorsdk%2Fpdfprocessor%2Fm_encrypt.htm
The idea would be to call the Encrypt() function above and pass a PrintingPerm argument of PRC_SEC_PRINT_PERM_NONE. You can also set other access permissions like modification, copy/paste, etc., if you like.
Hope this helps.
Related
I would like your opinion on whether something like this is possible or not.
1)Client logs in and uses a webform to submit data.
The data is then used to generate a PDF with a digital signature of the client's name and location and is then sent to our server. (i think this step is possible based on what i have read so far.Please correct me if i am wrong)
2)At some point later is it possible to pro-grammatically add additional content to the same pdf(perhaps in a different block) and then add another signature to the pdf?
Thanks! Any samples or examples achieving the same would be great as well.
The most critical point is
to programmatically add additional content to the same pdf(perhaps in a different block) and then add another signature to the pdf?
To do this without causing signature verifiers, in particular Adobe Reader, to consider the existing signature broken, you have to restrict your changes to those considered allowed for the signature type in question. For a listing of allowed changes look at this answer.
At best, therefore, you are allowed to:
Add signature fields
Add or edit annotations
Supply form field values
Digitally sign
(Supplying form field values includes instantiating page templates. Thus, if you prepare the pdf accordingly, you can even add new pages with content prepared but hidden in the originally signed pdf. Preparing page templates and instantiating them is not explicitly supported by all pdf libraries, though. Itext allows this only using low level api tricks.)
Background
Due to licencing on our Medical PDF Documents, our Doctors are restricted to only have 2-3 of them viewing a PDF document at once.
While we know we could just make a copy of everything and distribute it among everyone, our Doctors feel that they don't want to breach the licence, thus need an effective way to restrict access.
Challenge
While I understand the basic concept of this, I had the idea to use one of two ways:
Have folder access rights on the on the physical PC, to hard-limit the amount of users entering.
Store the information in a database, making the web application restrict the users.
Conclusion
I really don't want to use hard file access rights. This isn't nearly diverse enough for my liking.
I would rather have the application restrict access, because it will then be easier for me to set rights based on users.
My Question
If I did have it database side, I will go about storing the physical PDF's in a folder, then linking them to a page. This page will have a button to open the PDF, that will be enabled/disabled based on the current amount of people who have clicked on it.
When a person clicks 'Close' on the PDF, the application will -1 to the count, allowing a person to access the PDF.
How would I make my application know the PDF has closed?
You should display the pdf in an iframe and provide a "Close" button outside that iframe. This way you will be able to track your open documents' count and act accordingly.
I have a lotus notes web form in which computer-illiterate customers will use to attach Excel files and submit them to our company. I am using a Lotus Notes File Upload Control to allow them to do this, however, I need to default this File Upload Control to a certain directory location. I have already created a C# application the customers will be using, which places all of these excel files in a certain directory location, hence the reason I need to focus this File Upload Control. Unfortunately, some of the customers are computer challenged enough to not know how to navigate to these files on their own. Is this possible at all?
I'm assuming the users will be visiting a web page with the File Upload control, yes? If I'm misunderstanding please let me know and I'll delete this answer.
The simple answer is it isn't possible. The problem is that the browser can't know anything about the file structure of the clients that visit the site, so a "default path" property doesn't really make sense. It would likely only work in very specific environments (which is maybe true in your case, but not across the web in general)
I would investigate using the Notes API to have the C# program handle the upload without involving the browser client use of the file upload control. I don't know enough Java to be sure, but perhaps that might also be an option -- basically writing your own custom upload control that only asks the user for the filename.
You may also be seriously underestimating the ability of the users to follow directions. If your page identifies which directory the file will be found in, I expect most users will be able to follow the directions and upload from the correct directory.
So, I'm sure that accomplishing what you want to accomplish is possible in Notes, just not as simply as adding a default directory to the File Upload Control.
I need to create a web application that prints checks. Because of the nature of the program, it needs to be very secure, and each action needs to be logged. I need to be able to generate a check, print a check, allow reprints if needed, etc.
I've got the generation of the checks completed. I've decided to make a PDF (so that i don't get any browser header/footer garbage). What I'd like to do is not even save that PDF to a file but to instead send the data directly to a printer. Basically, I'd like for the user to enter the amount of the check, select which account it's going to be printed for, then click a button that sends the data for that check directly to the printer. I don't even want the user to be able to view the PDF of what's to be printed.
Has anyone done something similar to this in ASP.NET?
Thanks.
[EDIT]
The original question I asked was answered with ActiveX controls. I, however, decided to do it a different way. Instead of printing a PDF, I've decided to create an image of the background of the check. I will then use that image (.jpg), and manipulate it by placing the appropriate text (MICR line, amount, check date, etc.) on it using System.Drawing.Graphics and stored X,Y coordinates and font preferences in my DB. From there, I can use the System.Drawing.Printing namespace to send the new .jpg file to a network printer from the web server, eliminating the need for an activeX control and further tightening security because the new image of the finished check is never saved, and the user never has access to the overlay of the check.
Thanks for your help.
If you look at how postal services tackle this problem, you'll notice that a simple web application won't do. To have control over how and when items are sent to the printer, ActiveX compontents or Java software is used.
[Edit]
Small clarification: I ment that the software has to run on the client-side as opposed to your suggested server-side suggestion.
If you want to go the .NET route, you're down to an ActiveX in Managed C++ or a Click-Once application that is launched from the web (allows more of the .NET language, but can be decompiled and altered).
We have implemented this scenario in a couple of ways. First, we have the traditional PDF solution, where the server generates the PDF print image, returns it to the browser which is then displayed via the PDF plug-in and optionally printed.
Second, we wrote a client-side ActiveX component to handle the print. Pass the input values to a backend web service which uses FOP to format the print into PCL. The PCL is passed back to the ActiveX component who then sends the PCL directly to the users default printer. No PDF required here.
Either way works, but only the second option - which will require you to implement some client-side piece - meets all your requirements.
There isn't really a way to do this. You can only send a document to the user which the user can then send to the printer. There are ways to prompt the print dialogue to pop straight up, but the web would be pretty insecure if you were allowed to control how data was managed on the user's machine.
NKCSS is right that it would require software actually installed on the user's machine. You have done as much as you can by making it a PDF that the user is prompted to print.
If you had the cheque as html, you can used styles to show/hide content just for the printer as discussed in this post: here
There's no way to do this completely securely. Even if you force the PDF to print directly to the user's default printer, that itself could be a PostScript or PDF printer like PDFCreator. So they could still get a viewable PDF in the end.
This question asks how to restrict for a whole server. I just want to do so for a single report. I found a code snippet but it doesn't provide any clues on how to implement:
foreach (RenderingExtension extension in this.reportViewer.LocalReport.ListRenderingExtensions()) {
if (extension.Name == "PDF") {
((Extension)(extension.GetType().GetField("m_serverExtension", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(extension))).Visible = false;
}
I can't see how to make the report reference this code upon loading. Does anyone know how I am supposed to make the report execute this code?
EDIT: Incidentally report access is through the SSRS Report Manager web app. We are, in the main, delighted with this product so wouldn't consider reinventing the wheel in order to implement a hack to produce what is, essentially a "would be nice" feature.
It still boggles the mind slightly that the report's available rendering options are not controllable at the report level. Ho hum.
Incidentally I found this blog entry which clarifies the above code a little. Turns out we're talking about using a reportviewer component to limit the export options. Apparently this requires a dirty, dirty hack and besides it's not how we want to run our reporting function.
So unless anyone has a better idea than this within the next fortnight I'll mark this as the answer which basically sums up to:
You can only restrict functionality like this under certain conditions and by no means easily even when you do.
This seems like a clear failure in the wider fitness of SSRS for purpose as we have users who require Excel export functionality and users who need to be limited to PDF only. Oh well.
Does it matter?
Once they've downloaded the data and taken it offsite, you've lost it anyway.
You haven't really described how you are calling the reports - have you created some kind of application? Are you actually using the report viewer control?
You can generate a report in a specific format using the report URL and including the rs:Format parameter, e.g.
http://SERVER/reportserver?%2fSomeFolder%2fSomeReport&rs:Command=Render&rs:Format=PDF
The above URL generates the report as a PDF. You can also use the URL to hide the report toolbar etc. so you could create these URLs as links in your application, maybe one using just rs:Command=Render as a "View Report" link and one link that includes rs:Format=PDF as an "Export to PDF" link.
More on Reporting Services URL access.