How to remove or disable hyperlink events from pdf file? - asp.net

I can display a PDF file from byte[] in asp.net.
The problem is that it contains hyperlinks and I want to disable or remove these hyperlink events.

Docotic.Pdf, the library I am involved with, can be used to find hyperlinks in PDFs and remove them.
Here is the sample code that does exactly this:
public static void RemoveHyperlinks(string inputFile, string outputFile)
{
using (PdfDocument doc = new PdfDocument(inputFile))
{
foreach (PdfPage page in doc.Pages)
{
for (int i = 0; i < page.Widgets.Count; i++)
{
PdfWidget widget = page.Widgets[i];
PdfActionArea actionArea = widget as PdfActionArea;
if (actionArea != null)
{
PdfUriAction linkAction = actionArea.Action as PdfUriAction;
if (linkAction != null)
{
page.Widgets.RemoveAt(i);
i--;
}
}
}
}
doc.Save(outputFile);
System.Diagnostics.Process.Start(outputFile);
}
}
Please note that some viewers can detect hyperlinks from text and still present them as clickable areas even though there is not links defined in PDF itself. For example, Adobe Reader with certain settings can do just that.
P.S. I know this question is old, but maybe my answer will benefit new visitors.

You can libraries like this one to open and modify the PDF file and convert every hyperlink object to simple text.

Related

Xamarin Forms add new controls dinamically in the content via code

I have a form in my Xamarin project that its result is something like that:
Basically there is a header (1) and a body of this form (2). The header is quite simple build with AbsoluteLayout.
For creating the body (2) I've created my component to show a tab control and then for each tab a specific grid with images and text. For each section, I'm checking in the database how many records there are for it and change the text. This activity is very long and I'm trying to understand why and how I can improve speed.
Then I should cut the corner to add later in my page the tab control so the user can see immediately the header and after few second all page. The code is like the following:
public class MyPage : WaitingPage
{
public MyPage(Card card)
{
LoadingMessage = "Loading...";
ShowLoadingFrame = true;
ShowLoadingMessage = true;
ShadeBackground = true;
WaitingOrientation = StackOrientation.Vertical;
IsWaiting = true;
StackLayout stackPage = new StackLayout() {
BackgroundColor = Color.FromHex("#fff"),
Children = {
ShowHeader(card),
}
};
Content = stackPage;
Task.Yield();
Task.Run(async () => {
Content = await ShowDetails(card);
});
IsWaiting = false;
}
}
I tried different ways to add the content from await ShowDetails(card); but nothing happens. Basically the content doesn't change unless await ShowDetails(card); is executed. I discovered Task.Yield(); (you can wait the page is rendered and showed and then continue) but in this case doesn't work. And also WaitingPage doesn't show the message.
Any suggestions or help? Thank you in advance

Using translation strings in componentlinks

I've been trying to solve this problem since this morning, and I know I'm missing something obvious here but I can't seem to find it.
We are using an XML file that is published to the server which contains translations of all the standard words, such as 'read more'. It is a page with a component that is localized in the appropriate publication.
In our Razor templates we use the following code below a plain news Summary item which in turn links to the full item.
<a tridion:href="#news.ID" class="more" ><%=DefaultLabels.TranslatedTerm(((HomePage)Page).Location, "read_more")%></a>
Thing is, the server tag works just fine, but gets resolved as
<tridion:ComponentLink runat="server" PageURI="tcm:15-407-64" ComponentURI="tcm:15-1475" TemplateURI="tcm:0-0-0" AddAnchor="false" LinkText="<%= DefaultLabels.TranslatedTerm(((HomePage)Page).Location, "read_more") %>" LinkAttributes=" class="more"" TextOnFail="true"/>
As you might notice, it gets written as plain text on the page (no surprise there because the LinkText parameter is declared as String in the first place according to the liveDocs).
If I take away the
tridion:href
in the first example, and write it as
href
It works fine, the code resolves into a translated string and it's even linked... to nothing more than the TCM ID of the component, not the right page with the full news item on it.
I've tried creating a function in Razor, tried replacing the linkText, tried setting the ComponentLink in the template itself, but to no avail. I feel that it should work with just a minor adjustment to this template's code, but I fail to see it and I've started looking at custom TBB's to handle the code.
Anyone have an idea how to resolve this?
EDIT:
Chris' answer was actually the one I was looking for in this particular situation, but I feel that I should point out that Priyank's function is something that should be regarded as such as well. So thank you both for the help, it made my life somewhat easier now!
I hope this razor function will help you lot. This is very helpful function to render the link tag from the component link or external link.
#helper RenderLink(
dynamic link, // the link to render. Handles components + internal / external links
string cssClass = null, // optional custom CSS class
string title = null // optional link text (default is the title of the component being linked to)
)
{
if(link == null)
{
return;
}
if (title == null)
{
title = link.title;
}
string classAttr = string.IsNullOrEmpty(cssClass) ? "" : " class='" + cssClass + "'";
dynamic href;
string tridionLink = "";
string targetAttr = "";
if (link.Schema.Title == "External Link")
{
href = link.link;
}
else if (link.Schema.Title == "Internal Link")
{
href = link.link;
tridionLink = "tridion:";
}
else
{
href = link;
tridionLink = "tridion:";
}
if(link.target != null)
{
targetAttr = link.target == "New window" || link.target == "Popup" ? " target='_blank'" : "";
}
<a #(tridionLink)href="#href"#classAttr#targetAttr>#title</a>
}
I would suggest not using the default templates for resolving your links, rather output the link yourself something like this:
<tridion:ComponentLink runat="server" PageURI="tcm:15-407-64"
ComponentURI="tcm:15-1475" TemplateURI="tcm:0-0-0"
AddAnchor="false" LinkAttributes=" class="more""
TextOnFail="true">
<%=DefaultLabels.TranslatedTerm(((HomePage)Page).Location, "read_more") %>
</tridionComponentLink>
Better still you might consider outputting TCDL rather than the Taglib/ServerControl

How to dynamically and incrementally add controls to a container

I thought this was straight forward, but i have a link button, and I do this in the click event:
myContainer.Controls.Add( new FileUpload());
I expect 1 new file control upload to be spawned in the container for each click, however, I always get 1. What do I need to do to have multiple file upload controls?
Since the control was added dynamically, it does not survive the postback. This means that you have to add the file upload (or any other dynamically added control) again in the preinit event to be able to have its values populated and to use it later on in the page life cycle.
Sounds like you are trying to be able to upload multiple files. You may want to add the file uploads with jQuery and use the Request.Files property to get them on the back-end.
I agree with Becuzz's answer. Try this, there are better ways to do it, but this might help as well:
Add this to the "Load" event of your page
if (!IsPostBack) {
Session["UploadControls"] = null;
}
if (Session["UploadControls"] != null) {
if (((List<Control>)Session["UploadControls"]).Count > 0) {
foreach ( ctrl in (List<Control>)Session["UploadControls"]) {
files.Controls.Add(ctrl);
}
}
}
And also add this to the PreInit portion of your page:
string ButtonID = Request.Form("__EVENTTARGET");
if (ButtonID == "Button1") {
FileUpload NewlyAdded = new FileUpload();
List<Control> allControls = new List<Control>();
if (Session["UploadControls"] != null) {
if (((List<Control>)Session["UploadControls"]).Count > 0) {
foreach ( ctrl in (List<Control>)Session["UploadControls"]) {
allControls.Add(ctrl);
//Add existing controls
}
}
}
if (!allControls.Contains(NewlyAdded)) {
allControls.Add(NewlyAdded);
}
Session["UploadControls"] = allControls;
}
And add this to your HTML. This can be anything of course:
<div id="files" runat="server">
</div>
I use the "__EVENTTARGET" value to know what caused the postback, so that you don't get unwanted Upload controls.
Good luck, and hopefully this helps.
Hanlet

Can I print an HTMLLoader (pdf) in Adobe Air?

I'm using AlivePDF to create a PDF file, then save it to the desktop. I can then use an HTMLLoader to display my lovely PDF file.
Now, the print button in Adobe Reader works fine. However, there will be young children using the app, so I'd like to have a big "Print" button right above it.
I figured I could just start up a print job and feed it my HTMLLoader. This won't work because the HTML loader rasterizes the content.
Any suggestions?
One answer I have found in order to solve this problem is called Cross-scripting PDF content. The idea is that a PDF can have embedded JavaScript, which can be called from the JavaScript within the HTML page "housing" said PDF (object tag only, no embed).
This site was of particular help. I had to simplify the JavaScript from that page down quite a bit. I kept getting syntax errors.
I also need my program to generate the PDF and the HTML content. I cannot ship a single PDF with embedded JS and an HTML file pointing to it. They need to be dynamically generated by the user. Here is a basic rundown:
private function printText(text:String):void
{
var p:PDF=new PDF(Orientation.PORTRAIT, Unit.MM, Size.LETTER);
p.addPage();
p.addText(text, 100, 100);
p.addJavaScript(this.getJavascript());
var f:FileStream=new FileStream();
var html:File=File.desktopDirectory.resolvePath("exported.html");
f.open(html, FileMode.WRITE);
f.writeUTF(this.getHtml());
f.close();
var file:File=File.desktopDirectory.resolvePath("exported.pdf");
f.open(file, FileMode.WRITE);
var bytes:ByteArray=p.save(Method.LOCAL);
f.writeBytes(bytes);
f.close();
Now that we have our two files, HTML and PDF, we can view the PDF, and create a giant purple print button for our younger / sight-impared users.
if (HTMLLoader.pdfCapability == HTMLPDFCapability.STATUS_OK)
{
var win:PrintTitleWindow; //the window w/giant button
var htmlLoader:HTMLLoader=new HTMLLoader();
var url:URLRequest=new URLRequest(html.url);
htmlLoader.width=880;
htmlLoader.height=(appHeight - 150); //i figure out the height elsewhere
htmlLoader.load(url);
var holder:UIComponent=new UIComponent();
holder.addChild(htmlLoader);
win=PrintTitleWindow(PopUpManager.createPopUp(mainWindow, PrintTitleWindow, true));
win.width=900;
win.height=(appHeight - 50);
win.addChild(holder);
win.addContent(htmlLoader);
PopUpManager.centerPopUp(win);
}
}
Here is the JS and HTML I used. I'm adding these in here for laughs. I'm sure there is a better way to do this, but I'm tired and it is late.
private function getJavascript():String
{
return 'function myOnMessage(aMessage) { print({ bUI: true, bSilent: false, bShrinkToFit: true }); } function myOnDisclose(cURL,cDocumentURL) { return true; } function myOnError(error, aMessage) { app.alert(error); } var msgHandlerObject = new Object(); msgHandlerObject.onMessage = myOnMessage; msgHandlerObject.onError = myOnError; msgHandlerObject.onDisclose = myOnDisclose; this.hostContainer.messageHandler = msgHandlerObject;';
}
private function getHtml():String
{
return '<html><head><script>function callPdfFunctionFromJavascript(arg) { pdfObject = document.getElementById("PDFObj");pdfObject.postMessage([arg]);}</script></head><body><object id="PDFObj" data="exported.pdf" type="application/pdf" width="100%" height="100%"></object></body></html>';
}
The PrintTitleWindow is a simple title window with the print button on it. The code to print is simple.
myHtmlLoader.window.callPdfFunctionFromJavascript('Print');
Eh Voila! I have a gigantor-print-button like so:
(source: cetola.net)
Hitting that big purple print button is the same as hitting the print icon in the PDF toolbar. The difference for me is that my users, who could be elementary or middle-school kids, won't have to look around for the stupid button.
So, it's a long way around the block. Still, if you need to print and can't rely on that adobe toolbar button, here's your answer :) .

Detect and Activate Hyperlink in ASP.Net

I have a ASP.Net page for user to post their comments. Now I want that once user posts comments if any hypelink is found in the posted text then how can we make the hyperlink clickable.
Right now we are displaying the text and hyperlikn is not clickable
Use regular expressions to find hyperlink patterns. Then re-save the content with the html a tags.
EDIT: Here is an example to get you started, Run this as a console app to see whats going on:
class Program
{
static void Main(string[] args)
{
string s = "http://www.google.com is the best site, followed then by http://www.yahoo.com";
string pattern = #"http(s)?://([\w+?\.\w+])+([a-zA-Z0-9\~\!\#\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?";
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(pattern);
System.Text.RegularExpressions.MatchCollection matches = regex.Matches(s);
for (int i = 0; i < matches.Count; i++)
{
Console.WriteLine(string.Format("{1}", matches[i].Value, matches[i].Value)); }
}
}
The regular expression pattern was taken from: http://weblogs.asp.net/farazshahkhan/archive/2008/08/09/regex-to-find-url-within-text-and-make-them-as-link.aspx
response.write("The Link")

Resources