IText "IntelliSense" - pdf-generation

I need some guidance on achieving the below mentioned objective.
Develop something that can run as a scheduled job on Windows Server 2012 that can convert HTML file to PDF. We used to use Omniformat, but after migrating to Windows Server 2012, this is no longer an option as it will just stuck there.
I did some POC using iText, look promising except for the following points:
i. if the styling did not specify the font-family, IE will render it correctly, however IText will just print an empty block. This happened to my test case with Arabic and Russian characters.
<html>
<head></head>
<body>
Random Text, which I have no idea what are there.<br/>
<span style="font-family: Arabic Typesetting">This works!
Arabic : سعيد
</span>
<span> This isn't working
Arabic : سعيد
</span>
<br/>
<span>
Russian: Счастливый
</span>
<span style="font-family: MingLiu">
Simplfied Chinese: 快乐
</span>
<br/>
<span style="font-family: MingLiu">
Traditional Chinese: 快樂
</span>
</body>
</html>
What I have done so far.
I presume I have to have a customized TagProcessor.
public class MyParaGraph extends ParaGraph
{
#Override
public List<Element> content(WorkerContext arg0, Tag arg1, String arg2)
{
List<Element> elements = super.content(arg0, arg1,arg2);
Iterator<Element> eleIter = elements.iterator();
while( eleIter.hasNext())
{
Element element = eleIter.next();
List<Chunk> chunks = element.getChunks();
Iterator<Chunk> chunkIter = chunks.Iterator();
while (chunkIter.hasNext())
{
Chunk chunk = chunkIter.next();
for ( char charStr : arg2.toCharArray() )
{
//Intention is for future, if there is multiple Unicode characteres of different langauge, to create different chunk with differnt Font assigned.
//For now, quite useless loop,
//isarabic
if ( (code > 0x600 && code < code < 0x6FF) || (code > 0x750 && code < code < 0x77F))
{
//Pardon me, my dev is not linked to internet, i cant copy and paste so i just define a sub set.
if (chunk.getFont.getBaseFont()==null)
{
//It appear the processor failed to find the font-family style being define, as other tag with font-family define will not be null.
FontFactory.register("C:/Windows/Font/Arabaric Typesetting.ttf");
Font font = FontFactory.getFont("Arabaric TypeSetting");
chunk.setFont(font); //Its doesnt seems to update it to ask IText ot use Arabaric Typesetting..
}
}
}
}
}
}
}
HTMLPDFConverter.java
Main:
public static void main(String[] args){
TagProcessorFactory factory = Tags.getHtmlTagProcessorFactory();
factory.addProcessor(new MyParaGraph(), "p","span", "div");
Document doc = new Document();
PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream("D:/sample.pdf"));
writer.setPageSize(PageSize.A4);
document.open();
HtmlPipelineContext htmlContext = new HtmlPipelineContext (null);
htmlContext.setTagFactory(factory);
CssResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipleline(doc. writer)));
XMLWorker worker= new XMLWorker(pipeline, true);
XMLParser p = new XMLParser(worker);
p.parse( new InputStreamReader(new FileInputStream("D:/sample.html"), "UTF-8");
doc.close();
}
The Arabaric and Russian are not showing in the PDF.
Appreciate any advise.
Sorry for the mess, I can't copy and paste my POC code from development as they are on different network.
Thanks

Related

c# html agility pack pulling strings from html source code

I am just learning html agility pack and would like to extract a couple pieces of data from a website.
I want to store the item name and price into strings. I have html source code that contains 25 products
with 1 segment of the code posted below
I have very little xpath and html agility pack experience. and I am working on a class project to compare lowes and home depot prices for a few items.
I want to save string data_price = "14.97"; and string item = "Leaktite 5-Gal. Blue Bucket (Pack of 3)"
below is a portion of the source code I am working with
<div class="pod-inner">
<div class="productlist plp-pod__compare">
<div class="checkbox-btn js-podclick-analytics" data-podaction="compare">
<input type="checkbox" data-img="https://images.homedepot-static.com/productImages/8c1c50a0-e17c-4624-9e9e-35653052c1ce/svn/leaktite-paint-buckets-lids-209334-64_400_compressed.jpg" data-uom=" /package" data-price="$14.97" data-title="Leaktite 5-Gal. Blue Bucket (Pack of 3)" value="203924937" id="compare203924937" name="product" autocomplete="off" class="checkbox-btn__input">
so far I got
HtmlDocument doc = new HtmlDocument();
string home_bucket_url="https://www.homedepot.com/s/5%2520gallon%2520bucket?NCNI-5";
WebClient client = new WebClient();
string home_bucket_raw = client.DownloadString(home_bucket_url);
var findclasses = doc.DocumentNode.Descendants("input type").Where(d => d.Attributes.Contains("checkbox"));
foreach (var x in findclasses)
{
Console.WriteLine(x.ToString());
}
If you successfully selected node that you need (please debug to make sure), what you can do is simply get the attribute values that you need. Something like this:
x.Attributes["data-price"].Value;
x.Attributes["data-title"].Value;

Magento shop static block with different content in shops

so as you read title, i need help with magento static block, my task is to make static block content different in 2 shops, if it's even possible? ty for answers.
P.S. Sorry for bad english.
FYI the correct Magento way to do this in multi-store is to create 2 static block with the same ID and assign each one to the store view you want it to show on. Magento will load the correct version based on the current store being viewed.
Try this one it works for me. I made it with html/javascript. You can get store name by
var shopName= '{{config path="general/store_information/name"}}';
and then compare by your needs. Paste code into static block editor.
<!DOCTYPE html>
<html>
<body onload="websiteMessage()">
<p>Happy new years !!!</p>
<p id="static_block"></p>
<script>
function websiteMessage() {
var shopName= '{{config path="general/store_information/name"}}';
var string = "";
if(shopName.localeCompare("Leather_shoes_shop") == 0)
{
string = "leather shoes";
}
else if(shopName.localeCompare("Rubber_shoes_shop") == 0)
{
string = "rubber shoes";
}
else
{
string = "other";
}
document.getElementById('static_block').innerHTML = string;
}
</script>
</body>
</html>

How can I check the URL path to apply a condition (Razor)

I am using code like this to detect the browser and apply a condition to display or not display <label>:
#{
var settings = Model.PartFieldDefinition.Settings.GetModel();
System.Web.HttpBrowserCapabilitiesBase theBrow = Request.Browser;
}
<fieldset>
#{
if ((theBrow.Browser == "IE") && (theBrow.MajorVersion < 10))
{
#:<label>#Model.DisplayName</label>
#://Some Code for inputs
}
else
{
#://Some Code for inputs
}
}
</fieldset>
I have been trying to figure out if I can (and if so, how) I could utilize this logic to detect what path in the website the user is in to display or not display <label>
For example, on any other path I want the label displayed. However, for the pages under ~/Services (the path), I want to be able to hide the label.
It's a little bit more complicated than that. The code is in an editor template that gets used all over the site. If I use CSS in the editor template to "hide" the label I will affect all the pages. I was hoping with the above logic I can avoid that and only apply my logic on certain pages under a path.
Thanks.
Update
I have tried the following:
#{
string CurrentURL = Request.ApplicationPath;
}
<fieldset>
#{
if ((CurrentURL == "Services")) // also tried "/Services"
// rest of code left out for brevity
}
but the labels are hidden on all pages, even outside the path "~/Services". Am stuck on the syntax.
Found answer
I did the following:
#{
string CurrentURL = Request.Url.AbsoluteUri;
}
<fieldset>
#{
if (CurrentURL.Contains("Services"))
}
and it worked. I don't know if anyone can comment, but which would be better to use: Request.Url.AbsoluteUri or Request.Url.ToString() (both of which work)?

strict with CGI::AJAX

I have set of code for updating a password in the table, here I'm using CGI::AJAX module to update the password and get the popup screen on corresponding execution.When using that code with my application it is executing properly but I didn't get the output(means Perl subroutine is not called when JavaScript function to get use.password is not updated into table). I don't get any error either.
#!/usr/bin/perl -w
use strict;
use CGI;
use DBI;
use Data::Dumper;
my $p = new CGI qw(header start_html end_html h1 script link);
use Class::Accessor;
use CGI::Ajax;
my $create_newuser;
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
print $ajax->build_html($p,\&Show_html,{-charset=>'UTF-8', -expires=>'-1d'});
sub Show_html
{
my $html = <<EOHTML;
<html>
<body bgcolor="#D2B9D3">
<IMG src="karvy.jpg" ALT="image">
<form name='myForm'>
<center><table><tr><td>
<div style="width:400px;height:250px;border:3px solid black;">
<center><h4>Create New Password's</h4>
<p>&nbsp User Name</b>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<INPUT TYPE="text" NAME="user" id = "user" size = "15" maxlength = "15" tabindex = "1"/></p>
<p>&nbsp Password:</b>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<INPUT TYPE=PASSWORD NAME="newpassword" id = "newpassword" size = "15" maxlength = "15" tabindex = "1"/></p>
<p>&nbsp Re-Password:</b>&nbsp&nbsp&nbsp<INPUT TYPE=PASSWORD NAME="repassword" id = "repassword" size = "15" maxlength = "15" tabindex = "1"/></p>
<input type="submit" id="val" value="Submit" align="middle" method="GET" onclick="fetch_javaScript(['user','newpassword','repassword']);"/><INPUT TYPE="reset" name = "Reset" value = "Reset"/>
<p>Main Menu <A HREF = login.pl>click here</A>
</center>
</div>
</td></tr></table></center>
</form>
</body>
</html>
EOHTML
return $html;
}
$create_newuser =sub
{
my #input = $p->params('args');
my $user=$input[0];
my $password=$input[1];
my $repassword=$input[2];
my $DSN = q/dbi:ODBC:SQLSERVER/;
my $uid = q/123/;
my $pwd = q/123/;
my $DRIVER = "Freetds";
my $dbh = DBI->connect($DSN,$uid,$pwd) or die "Coudn't Connect SQL";
if ($user ne '')
{
if($password eq $repassword)
{
my $sth=$dbh->do("insert into rpt_account_information (user_id,username,password,user_status,is_admin) values(2,'".$user."','".$password."',1,1)");
my $value=$sth;
print $value,"\n";
if($value == 1)
{
print 'Your pass has benn changed.Return to the main page';
}
}
else
{
print "<script>alert('Password and Re-Password does not match')</script>";
}
}
else
{
print "<script>alert('Please Enter the User Name')</script>";
}
}
my $create_newuser;
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
...;
$create_newuser =sub { ... };
At the moment when you create a new CGI::Ajax object, the $create_newuser variable is still undef. Only much later do you assign a coderef to it.
You can either assign the $create_newuser before you create the CGI::Ajax:
my $create_newuser =sub { ... };
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
...;
Or you use a normal, named subroutine and pass a coderef.
my $ajax = new CGI::Ajax('fetch_javaScript' => \&create_newuser);
...;
sub create_newuser { ... }
Aside from this main error, your script has many more problems.
You should use strict instead of the -w option.
For debugging purposes only, use CGI::Carp 'fatalsToBrowser' and sometimes even with warningsToBrowser can be extremely helpful. Otherwise, keeping a close eye on the error logs is a must.
my $p = new CGI qw(header start_html end_html h1 script link) doesn't make any sense. my $p = CGI->new should be sufficient.
use Class::Accessor seems a bit random here.
The HTML in Show_html is careless. First, your heredocs allows variable interpolation and escape codes – it has the semantics of a double quoted string. Most of the time, you don't want that. Start a heredoc like <<'END_OF_HTML' to avoid interpolation etc.
Secondly, look at that tag soup you are producing! Here are some snippets that astonish me:
bgcolor="#D2B9D3", align="middle" – because CSS hasn't been invented yet.
<center> – because CSS hasn't been invented yet, and this element isn't deprecated at all.
<table><tr><td><div ... </div></td></tr></table> – because there is nothing wrong with a table containing a single cell. (For what? This isn't even for layout reasons!) This table cell contains a single div …
… which contains another center. Seriously, what is so great about unneccessary DOM elements that CSS isn't even an option.
style="width:400px;height:250px;border:3px solid black;" – because responsive design hasn't been invented yet.
<p> ... </b> – Oh, what delicious tag soup!
&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp – this isn't a typewriter, you know. Use CSS and proper markup for your layout. There is a difference between text containing whitespace, and empty areas in your layout.
tabindex = "1" … tabindex = "1" … tabindex = "1" – I don't think you know what tabindex does.
<A HREF = login.pl> – LOWERCASING OR QUOTING YOUR ATTRIBUTES IS FOR THE WEAK!!1
onclick="fetch_javaScript(['user','newpassword','repassword']);" – have you read the CGI::Ajax docs? This is not how it works: You need to define another argument with the ID of the element where the answer HTML is displayed.
In your create_newuser, you have an SQL injection vulnerability. Use placeholders to solve that. Instead of $sth->do("INSERT INTO ... VALUES('$foo')") use $sth->do('INSERT INTO ... VALUES(?)', $foo).
print ... – your Ajax handler shouldn't print output, instead it should return a HTML string, which then gets hooked into the DOM at the place your JS function specified. You want something like
use HTML::Entities;
sub create_newuser {
my ($user, $password, $repassword) = $p->params('args');
my ($e_user, $e_password) = map { encode_entities($_) } $user, $password;
# DON'T DO THIS, it is a joke
return "Hello <em>$e_user</em>, your password <code>$e_password</code> has been successfully transmitted in cleartext!";
}
and in your JS:
fetch_javaScript(['user','newpassword','repassword'], ['answer-element'], 'GET');
where your HTML document somewhere has a <div id="answer-element" />.

Testing image crops existence with Razor in Umbraco

I have created some Razor code to output images onto a page if the exist. It is detailed below and contains some simple checks to prevent rendering a blank list item. The site has gone live and works fine. The client then deleted the image from the media folder within Umbraco, meaning my node had a valid image assigned but the image just didn't exists. I got the following exception:
'string' does not contain a definition for 'crops'
How do I deal with this?
#using umbraco.MacroEngines;
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.presentation.nodeFactory
#using umbraco.cms.businesslogic.media
<ul>
#foreach (dynamic client in #Model.Children)
{
var image = Model.MediaById(client.Logo);
var crops = image.imageCropper.crops;
<li>
<h2><span>#client.Name</span></h2>
#if (crops != null || crops.GetType().ToString() != "System.String")
{
<span class="itemImage">
<img src="#crops.Find("#name", "cropname").url" alt="#client.Name" />
</span>
}
</li>
}
</ul>
In this case you'll probably need to do a type check. I believe the MediaById method should return a DynamicNode if it's valid, so something like the following should work:
if(image.GetType() == typeof(DynamicNode))
{
...
}
I was getting this issue. What I found is that the Model.MediaById(imageid) call would throw an exception if the Media had been deleted (and had already been picked in the past).
So I setup my test like this:
dynamic mainMediaImage = new DynamicNull();
try
{
mainMediaImage = Model.MediaById(related.eventMainImage);
}
catch(Exception e)
{
<p style='display: none;'>#e.Message</p>
}
var cropUrl = "";
if(mainMediaImage.GetType() == typeof(DynamicMedia))
{
cropUrl = GetImageCropperUrl(Model.MediaById(related.eventMainImage).crops, "List Image");
}
I still get the error, but it doesn't display to the user.
I found it would never get to my DynamicMedia check so I had to add the try...catch() around the call or else to entire Macro would fail.

Resources