Convert local HTML file to PDF with wkhtmltopdf C library - c++

I am using the wkhtmltopdf C library to convert a local HTML file to PDF, but no matter what I've tried, it does not successfully convert the file. Using an external URI (like google.com) works fine, however any local files will fail, either with no error message or with HTTP error codes 1003 or 1302.
Here is the code I am using:
wkhtmltopdf_global_settings *globalSettings;
wkhtmltopdf_object_settings *objectSettings;
wkhtmltopdf_converter *converter;
wkhtmltopdf_init(1);
globalSettings = wkhtmltopdf_create_global_settings();
wkhtmltopdf_set_global_setting(globalSettings, "size.paperSize", "A4");
wkhtmltopdf_set_global_setting(globalSettings, "orientation", "Portrait");
wkhtmltopdf_set_global_setting(globalSettings, "colorMode", "Color");
wkhtmltopdf_set_global_setting(globalSettings, "size.paperSize", "A4");
wkhtmltopdf_set_global_setting(globalSettings, "out", "output.pdf");
converter = wkhtmltopdf_create_converter(globalSettings);
objectSettings = wkhtmltopdf_create_object_settings();
wkhtmltopdf_set_object_setting(objectSettings, "load.blockLocalFileAccess", "false");
wkhtmltopdf_set_object_setting(objectSettings, "page", "inputfile.html");
wkhtmltopdf_add_object(converter, objectSettings, NULL);
if (wkhtmltopdf_convert(converter) != 1)
{
qWarning(qPrintable("Error code: " + QString::number(wkhtmltopdf_http_error_code(converter))));
}
wkhtmltopdf_destroy_converter(converter);
wkhtmltopdf_deinit();
I am using QT, and the input file is within a resource file of mine. I have tried many variation to get wkhtmltopdf to load the file, but none of the following have worked (some liberties have been taken with the below source, but you should get the idea):
I tried to copy the contents of the input file into a QTemporaryFile, and load that file:
QTemporaryFile temp;
if (temp.open())
{
temp.write(inputFile.readAll());
wkhtmltopdf_set_object_setting(objectSettings, "page", temp.fileName());
}
I tried using the resource file path directly:
wkhtmltopdf_set_object_setting(objectSettings, "page", ":templates/input.html");
I've also tried adding in file:// for the above attempts. Does anyone have any idea why it may not be working, and if so, how to fix it?

The Qt resource paths will most likely not work. The resource paths are only visible to APIs that internally use QFile and use the same copy of the Qt library as your code is using.
The approach with temporary files is a decent workaround.
But this line can't really work:
wkhtmltopdf_set_object_setting(objectSettings, "page", temp.fileName());
The type that you pass (a QString) is wrong. Unfortunately, the interface is C-like and there's no type safety, so you're lulled into complacency. You need to pass it a utf8-encoded file path:
wkhtmltopdf_set_object_setting(objectSettings, "page",
temp.fileName().toUtf8().constData());

Related

Is there a way to write to the aws config file in node?

I want to load the AWS config file and edit the contents of the file.
I found #aws-sdk/shared-ini-file-loader, that works well to load the config file data as the JSON object.
import { loadSharedConfigFiles } from '#aws-sdk/shared-ini-file-loader'
let awsFileContents = await loadSharedConfigFiles({ configFilepath: '~/.aws/config' })
console.log(awsFileContents.configFile)
Now I want to perform some changes in the awsFileContents.configFile object, parse it back to the correct format, and write it back to the ~/.aws/config file.
Is there an AWS module available that can do that?
I have tried ini, multi-ini, and conf-cfg-ini. But they have issues while parsing the JSON back to the correct format.
You do not need the SDK to read/write the config file. It is a normal INI file you can modify with standard tools for INI files.
You can use e.g. the ini package for this: https://www.npmjs.com/package/ini
In other languages like Python and also for my "AWS Manager" (Windows application written in Delphi) I use simple ini function to read and also write the config file without any issues.

Initialize tesseract without any external resources (languages/dictionaries)

I am currently writing a C++ program that should read hex data from JPEG images. I have to compile it into one single windows executable without any external resources (like the "tessdata" directory or config files). As I am not reading any words or sentences, I don't need any dictionaries or languages.
My problem is now that I could not find a way to initialize the API without any language files. Every example uses something like this:
tesseract::TessBaseAPI api;
if (api.Init(NULL, "eng")) {
// error handling
return -1;
}
// do stuff
I also found that I can call the init function without language argument and with OEM_TESSERACT_ONLY:
if(api.Init(NULL, NULL, tesseract::OcrEngineMode::OEM_TESSERACT_ONLY)) {
// ...
}
This should disable the language/dictionary, but NULL just defaults to "eng". It seems like tesseract still wants a language file to initialize and will disable it afterwards.
This also seems to be the case for any other solutions I found so far: I always need .traineddata files to initialize the api and can disable them afterwards or using config files.
My question is now:
Is there any way to initialize the tesseract API in C++ using just the executable and no other resource files?
No. Tesseract always needs some language (default is eng) + osd (.traineddata) files. Without language data file tesseract is useless.
Your post seems that you made several wrong assumptions (e.g. about OEM_TESSERACT_ONLY), so maybe if you describe what you try to achieve with tesseract you can get better advice.

ofstream not creating file (Node.js addon)

I am attempting to create an addon for Node.js that (among other things) writes content to a file inside my C++ class using ofstream.
std::ofstream license_file;
std::string fileContent(*NanAsciiString(args[0]));
license_file.open(PATH);
//file doesn't yet exist, so create it
if(!license_file) {
printf("ERROR: %s (%s)\n", strerror(errno), PATH);
}
license_file << fileContent;
license_file.close();
This works fine if PATH is set to the same directory as my Node.js code (e.g. ./license.txt).
However, ofstream fails to open/create the file in question if it is located anywhere else. For example, using ~/license.txt does not work (note: I'm running OSX).
The error reported is always No such file or directory -- even after I physically create ~/license.txt.
Any ideas why this works in one directory but not others? If it were a permissions issue I would expect a different error message.
For the record, I've seen about 20 other SO questions about "ofstream fails to create file" but passing additional flags into open() has no effect. I have a feeling this is somehow related to running inside Node/V8.
I think the issue is that you need to find out the user directory in a different way than using ~.

Using Firefox website information in C++ program

I am trying to extract information from "about:plugins" website when you use Firefox web browser. I want to be able to use the contents of the website in my C++ program. Only way I know how to use content from another location is reading from a file.
What I am trying to do is read the file name and file path for each plugin from about:plugin'
Not sure if I could send this information to a file and then read it from there, but that seems like double work since if it output to file, I could just read it from there.
Needed to know how to extract information from the Firefox website in order to be used in a C++ program.
Just parse the pluginreg.dat file, you can find it in:
C:\Users\xxxxxxx\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxx.default
To obtain the AppData
char cAppData[MAX_PATH];
if(SHGetSpecialFolderPathA(NULL, cAppData, CSIDL_APPDATA, false))
{
// To obtain the profile name, parse the profiles.ini file in the folder
// ...AppData\Roaming\Mozilla\Firefox
// ...
}

Getting full path of file in COCOS2D-X on Android devices

I am trying to obtain an XML file in my project but I can't seem make work right.
I am using libXML (the one that comes with cocos2d-x-2.0.4) to parse XML files.
I'm using CCFileUtils::sharedFileUtils() -> fullPathFromRelativePath( ); but the problem is, for Android versions, it will not give the full path. It works fine on iOS, though.
I then looked at the GitHub and saw something weird. It turns out that fullPathFromRelativePath( ) will only return whatever you pass onto it.
From the GitHub:
const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath)
{
return pszRelativePath;
}
I've looked everywhere and all I get is how to read XML files using CCFileUtils. I am already able to parse XML files. The only issue is that I can't get the full path of the XML file using fullPathFromRelativePath() in Android.
How can I get the full path of the XML file in Android?
There is nothing wrong with that function. The problem is that your xml files are inside apk, which is a zipped file, you cannot read that file directly, you should use something like
long tmpSize;
const char* xmlData = CCFileUtils::sharedFileUtils()->getFileData(YOUR_PATH_TO_FILE, "r", &tmpSize);
then you can use lib xml to handle the data you get.
but remember you cannot modify anything inside apk file. if you want to write to xml, you need to copy it to some writable path first (like sdcard or using getWritablePath()).
For the files not inside apk, you can use fopen() directly, you do not need getFileData() any more.
Hope this helps.