BadPasswordException when filling out pdf with iTextSharp - pdf-generation

I have a third-party PDF file with some form fields, that I need to fill out programmatically. PDF file is secured. Detailed security settings: SecurityMethod: Password Security, Document Open Password: No, ... Form Field Fill-in or Signing: Allowed...
When I'm trying to open and fill out the document manually, everything is ok, and I'm not asked for any password. But with the code, it fails with exception.
Here's the code (I'm using iTextSharp library):
var str = new MemoryStream();
var reader = new PdfReader(_path);
var stamper = new PdfStamper(reader, str);
Creating the PdfStamper object fails with exception: BadPasswordException. PdfReader not opened with owner password.
Any ideas, why it fails with code, but not manually?
Thanks in advance.

Have you tried adding
PdfReader.unethicalreading = true;
before your reader initialization?

Related

How to encrypt pdf files securely

I have an application, where spring-boot is back-end and jquery is front-end. I can create document but without encryption or any kind of protection, so i need to figure it out.
I need to secure pdf files. What is the best way to do that?
I could add option to set passwords for that pdf file on the front-end side. So user who has permission to create documents would set password for him and for users who can access the document.
The same story, but creator of document would only choose password for normal users and the "main" password would be secretely used only on the back-end side
How would I store those passwords? In database? And how/which format?
How would I distribute those passwords to users? Is it safe to use email for sending this password to users? But again, the password must be somewhere securely stored.
Is it a good approach? Or what would be the best to do this?
Thanks
I think your concerns can be easiely handled by the IText Engine.
This toolkit comes with handy features for PDF Generation and Manipulation( including secure PDF with password and other signature encryption systems).
Here is a basic example :
PdfReader reader = new PdfReader(src);
WriterProperties props = new WriterProperties()
.setStandardEncryption(USERPASS, OWNERPASS, EncryptionConstants.ALLOW_PRINTING,
EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA);
PdfWriter writer = new PdfWriter(new FileOutputStream(dest), props);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
pdfDoc.close();
NOTE :
Note that USERPASS and OWNERPASS are of type byte[]
public static byte[] USERPASS = "superuser".getBytes(); public static byte[] OWNERPASS = "superowner".getBytes();
You have different options for the permissions (look for EncryprionConstants starting with ALLOW_) and also you can chose from different encryption algorithms.

How to download file in Xamarin.Forms that are in Base64 format?

I am creating an application that download and upload attachment from the Xamarin.Forms application.
I am using .Net standard project and try to use with the "CrossDownloadManager" Nuget but it is not compatible and other reference for download file are using url but in this situation I have base64byte string.
I also try with This reference but it doesn't work for me.
Application works on Android and iOS.
I attached sample response Here:
Can anyone look into this and suggest me what should I have to do in that?
download a file given a url
var client = new HttpClient();
var data = await client.GetStringAsync(url);
if data is Base64, decode it
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
var decoded = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
save decoded string
File.WriteAllText(filepath, decoded);

Xamarin Android share PDF. Permission denied for the attachment [duplicate]

My app creates mails with attachments, and uses an intent with Intent.ACTION_SEND to launch a mail app.
It works with all the mail apps I tested with, except for the new Gmail 5.0 (it works with Gmail 4.9), where the mail opens without attachment, showing the error: "Permission denied for the attachment".
There are no useful messages from Gmail on logcat. I only tested Gmail 5.0 on Android KitKat, but on multiple devices.
I create the file for the attachment like this:
String fileName = "file-name_something_like_this";
FileOutputStream output = context.openFileOutput(
fileName, Context.MODE_WORLD_READABLE);
// Write data to output...
output.close();
File fileToSend = new File(context.getFilesDir(), fileName);
I'm aware of the security concerns with MODE_WORLD_READABLE.
I send the intent like this:
public static void compose(
Context context,
String address,
String subject,
String body,
File attachment) {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("message/rfc822");
emailIntent.putExtra(
Intent.EXTRA_EMAIL, new String[] { address });
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
emailIntent.putExtra(
Intent.EXTRA_STREAM,
Uri.fromFile(attachment));
Intent chooser = Intent.createChooser(
emailIntent,
context.getString(R.string.send_mail_chooser));
context.startActivity(chooser);
}
Is there anything I do wrong when creating the file or sending the intent? Is there a better way to start a mail app with attachment? Alternatively - has someone encountered this problem and found a workaround for it?
Thanks!
I was able to pass a screenshot .jpeg file from my app to GMail 5.0 through an Intent. The key was in this answer.
Everything I have from #natasky 's code is nearly identical but instead, I have the file's directory as
context.getExternalCacheDir();
Which "represents the external storage directory where you should save cache files" (documentation)
GMail 5.0 added some security checks to attachments it receives from an Intent. These are unrelated to unix permissions, so the fact that the file is readable doesn't matter.
When the attachment Uri is a file://, it'll only accept files from external storage, the private directory of gmail itself, or world-readable files from the private data directory of the calling app.
The problem with this security check is that it relies on gmail being able to find the caller app, which is only reliable when the caller has asked for result. In your code above, you do not ask for result and therefore gmail does not know who the caller is, and rejects your file.
Since it worked for you in 4.9 but not in 5.0, you know it's not a unix permission problem, so the reason must be the new checks.
TL;DR answer:
replace startActivity with startActivityForResult.
Or better yet, use a content provider.
Use getExternalCacheDir() with File.createTempFile.
Use the following to create a temporary file in the external cache directory:
File tempFile = File.createTempFile("fileName", ".txt", context.getExternalCacheDir());
Then copy your original file's content to tempFile,
FileWriter fw = new FileWriter(tempFile);
FileReader fr = new FileReader(Data.ERR_BAK_FILE);
int c = fr.read();
while (c != -1) {
fw.write(c);
c = fr.read();
}
fr.close();
fw.flush();
fw.close();
now put your file to intent,
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
You should implement a FileProvider, which can create Uris for your app's internal files. Other apps are granted permission to read these Uris. Then, simply instead of calling Uri.fromFile(attachment), you instantiate your FileProvider and use:
fileProvider.getUriForFile(attachment);
Google have an answer for that issue:
Store the data in your own ContentProvider, making sure that other apps have the correct permission to access your provider. The preferred mechanism for providing access is to use per-URI permissions which are temporary and only grant access to the receiving application. An easy way to create a ContentProvider like this is to use the FileProvider helper class.
Use the system MediaStore. The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device.
Also you can try set permissions for your file:
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
And finally you can copy/store your files in external storage - permissions not needed there.
I tested it and I found out that it was definitely private storage access problem.
When you attach some file to Gmail (over 5.0) do not use the file from private storage such as /data/data/package/. Try to use /storage/sdcard.
You can successfully attach your file.
Not sure why GMail 5.0 doesn't like certain file paths (which I've confirmed it does have read access to), but an apparently better solution is to implement your own ContentProvider class to serve the file. It's actually somewhat simple, and I found a decent example here: http://stephendnicholas.com/archives/974
Be sure to add the tag to your app manifest, and include a "android:grantUriPermissions="true"" within that. You'll also want to implement getType() and return the appropriate MIME type for the file URI, otherwise some apps wont work with this... There's an example of that in the comment section on the link.
I was having this problem and finally found an easy way to send email with attachment. Here is the code
public void SendEmail(){
try {
//saving image
String randomNameOfPic = Calendar.DAY_OF_YEAR+DateFormat.getTimeInstance().toString();
File file = new File(ActivityRecharge.this.getCacheDir(), "slip"+ randomNameOfPic+ ".jpg");
FileOutputStream fOut = new FileOutputStream(file);
myPic.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
file.setReadable(true, false);
//sending email
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"zohabali5#gmail.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Recharge Account");
intent.putExtra(Intent.EXTRA_TEXT, "body text");
//Uri uri = Uri.parse("file://" + fileAbsolutePath);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(Intent.createChooser(intent, "Send email..."),12);
}catch (Exception e){
Toast.makeText(ActivityRecharge.this,"Unable to open Email intent",Toast.LENGTH_LONG).show();
}
}
In this code "myPic" is bitmap which was returned by camera intent
Step 1: Add authority in your attached URI
Uri uri = FileProvider.getUriForFile(context, ""com.yourpackage", file);
Same as your manifest file provide name
android:authorities="com.yourpackage"
Step 2`; Add flag for allow to read
myIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

Opening a PDF file in Windows Phone

I'm developing an app for Windows Phone 7 and I'm using a Phonegap template for it.
Everything looks perfect, but now I’m stuck trying to open a PDF file in the browser.
I tried the following but that doesn’t work because the url of the PDF exceeds the 2048 character limit (it’s a data url). This code runs after the deviceReady event was fired.
var ref = window.open('http://www.google.com', '_blank', 'location=no');
ref.addEventListener('loadstart', function () { alert(event.url); });
Now, I'm trying to save the PDF file to storage and then I'm trying to have it opened by the browser, but the browser doesn't show anything. I'm editing the InAppBrowser.cs code from cordovalib and I added the following lines before calling browser.Navigate(loc);
private void ShowInAppBrowser(string url)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
FileStream stream = store.OpenFile("test.pdf", FileMode.Create);
BinaryWriter writer = new BinaryWriter(stream);
var myvar = Base64Decode("the big data url");
writer.Write(myvar);
writer.Close();
if (store.FileExists("test.pdf")) // Check if file exists
{
Uri loc = new Uri("test.pdf", UriKind.Relative);
...
}
}
This code is returning the following error:
Log:"Error in error callback: InAppBrowser1921408518 = TypeError: Unable to get value of the property 'url': object is null or undefined"
I don’t wanna use ComponentOne.
Any help would be greatly appreciated!
You cannot open pdf files from the isolated storage in the default reader for PDF files. If the file is online e.g. it has a URI for it, you can use WebBrowserTask to open it since that will download and open the file in Adobe Reader.
On Windows Phone 8 you actually can open your own file in default file reader for that extension, but I am not sure how that will help you since you target PhoneGap and Windows Phone 7.
Toni is correct. You could go and try to build your own viewer (which would be the same thing as using C1, but with more time involved). I worked on a port of iTextSharp and PDFSharp for WP7, but neither of which are PDF Viewers. They are good for creating PDFs and parsing them some (but to render them there is more work involved). This has been a personal quest of mine, but honestly the best I have gotten is to be able to extract some images from the PDF (and none of the text)
try this
var installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assets = await installedLocation.GetFolderAsync("Assets");
var pdf = await assets.GetFileAsync("metro.pdf");
Windows.System.Launcher.LaunchFileAsync(pdf);
This worked correctly on my Device.

HtmlUnit and saving page as PDF

In the Java EE environment, I want to load an XML and XSL file, render the output to a browser window, and save the rendered page as PDF.
I would like to do it all programmatically. I was looking at HtmlUnit to use as a headless browser. That part seems to work, but does HtmlUnit have any API to invoke a "print" function or similar function to persisted the rendered output? I was thinking of some way to link it in with iText.
I would recommend trying out flying-saucer which in this case basically is a CSS/XHTML enabled iText wrapper.
I wrote a simple example below. Don't forget the necessary dependencies for HtmlUnit and flying-saucer.
//Set up a new WebClient using your favourite settings
WebClient webClient = new WebClient();
//Fetch page
HtmlPage page = webClient.getPage("url-to-target.resource");
//Set PDF target output file
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);
//Set up flying-saucer IText based renderer
ITextRenderer renderer = new ITextRenderer();
//Create PDF
renderer.setDocumentFromString(page.asXml();
renderer.layout();
renderer.createPDF(os);
os.close();
If you're doing reporting in Java i highly recommend you to use Jasper Reports, it's relatively easy to use, you can design the report graphically and it can take XML as input and give you a report in many formats (including PDF).

Resources