How To find Cross References(Internal Links) In Pdf File Using ItextSharp Lib - c#-4.0

Hi I am using ItextSharp For searching Cross References(Internal Links) In pdf file. I already done with External Links.
Please Post If u have any solutions.
//Get the current page
PdfDictionary PageDictionary = R.GetPageN(page);
//Get all of the annotations for the current page
PdfArray Annots = PageDictionary.GetAsArray(PdfName.ANNOTS);
//Make sure we have something
if ((Annots == null) || (Annots.Length == 0))
// return null;
{
Console.WriteLine("nothing");
}
//Loop through each annotation
if (Annots != null)
{
foreach (PdfObject A in Annots.ArrayList)
{
//Convert the itext-specific object as a generic PDF object
PdfDictionary AnnotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(A);
//Make sure this annotation has a link
if (!AnnotationDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.LINK))
continue;
//Make sure this annotation has an ACTION
if (AnnotationDictionary.Get(PdfName.A) == null)
continue;
//Get the ACTION for the current annotation
PdfDictionary AnnotationAction = AnnotationDictionary.GetAsDict(PdfName.A);
// PdfDictionary AnnotationAction = (PdfDictionary)AnnotationDictionary.Get(PdfName.A);
//Test if it is a URI action (There are tons of other types of actions, some of which might mimic URI, such as JavaScript, but those need to be handled seperately)
if (AnnotationAction.Get(PdfName.S).Equals(PdfName.URI))
{
PdfString Destination = AnnotationAction.GetAsString(PdfName.URI);
string url1 = Destination.ToString();
}
}
}

You've already done most of the work. Please take a look at the following screen shot:
You see the /Annots array of a page. You are already parsing that array in your code and you skip all annotations that aren't of the /Subtype /Link or don't have an /A key, which is excellent.
Currently you're only looking for values of /S that are of type /URI. You say you're already done with external links, but that's not true: you should also lok for entries where /S is /GoToR (remote goto). If you want internal links, you need to look for /S values equal to /GoTo, /GoToE, and (in the future) /GoToDp. Maybe you also want to remove the /JavaScript actions, because they can also be used to jump to a specific page.
Please download The ABC of PDF and take a look at table 3.11 for more info. (The book is available for free.)

Related

Getting document attachments using Kentico API

I created book store site on Kentico i used only their adminstration and display the data from my website using Kentico API's but am strugled in getting attachment files related to specific document i've got document data with no problem using
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
var documents = tree.SelectNodes("CMS.Product");
need also to get related attachment files like book PDFs.. i've tried to use
DocumentAttachment
AttachmentInfo
AttachmentInfoProvider
classes but i couldn't get the data .. I would appreciate if any one help me in that.
Actually am searching about something like GetAttachment().Where("AttachmentFile","Ënglish File")
You can filter the returned attachments based on their values in columns (CMS_Attachment table) by using a code like this:
var attachment = AttachmentInfoProvider.GetAttachments()
.WhereEquals("AttachmentName", "Englishfile")
.And()
.WhereEquals("AttachmentExtension", "jpg")
.TopN(1)
.FirstOrDefault();
if (attachment != null)
{
// attachment was found
}
This code will get one .jpg file where attachment name equals to "EnglishFile"
Solved after using something like
var Attachment = AttachmentInfoProvider.GetAttachments(226, true);
This is from Kentico documentation. This example shows how to add an attachment and modify its metadata. You can ignore that part.You will have to make it generic to work for all examples.
Kentico 9 API Links
// Creates a new instance of the Tree provider
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
// Gets a page
TreeNode page = tree.SelectSingleNode(SiteContext.CurrentSiteName, "/Articles", "en-us");
if (page != null)
{
// Gets an attachment by file name
AttachmentInfo attachment = DocumentHelper.GetAttachment(page, "file.png", tree);
// Edits the attachment's metadata (name, title and description)
attachment.AttachmentName += " - modified";
attachment.AttachmentTitle = "Attachment title";
attachment.AttachmentDescription = "Attachment description.";
// Ensures that the attachment can be updated without supplying its binary data
attachment.AllowPartialUpdate = true;
// Saves the modified attachment into the database
AttachmentInfoProvider.SetAttachmentInfo(attachment);
}

Making jslink target specific list

Background
I got a page where I’m showing two list views from two separate lists which both have Custom List as their ListTemplate. They got their separate jslink file cause I don’t want them to look alike.
Problem
The js link file targets both listviews since they use the same Template.
Code
(function () {
var listContext = {};
listContext.Templates = {};
listContext.ListTemplateType = 100;
listContext.Templates.Header = "<div><ul>";
listContext.Templates.Footer = "</ul></div>";
listContext.Templates.Item = LinkTemplate;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(listContext);
})();
Question
Is there any way to make the js only target a specific list?
Ended up going with Paul Hunts solution that he writes about on myfatblog.co.uk. http://www.myfatblog.co.uk/index.php/2013/09/listview-web-part-issues-with-jslink-and-display-templates-a-solution/
The script ended up looking like this and I pasted it into the jslink function where I define what listContext to override.
// Override the RenderListView once the ClientTemplates.JS has been called
ExecuteOrDelayUntilScriptLoaded(function(){
// Copy and override the existing RenderListView
var oldRenderListView = RenderListView;
RenderListView = function(ctx,webPartID)
{
// Check the title and set the BaseViewId
if (ctx.ListTitle == "List")
ctx.BaseViewID = "list";
//now call the original RenderListView
oldRenderListView(ctx,webPartID);
}
},"ClientTemplates.js");

Check URL exists in ApplicationContentUriRules

I have an app that is loading URLs into a WebView (x-ms-webview). When the user makes the request, I would like to compare the URL they are trying to load with the "whitelisted" URLs in the ApplicationContentUriRules and warn them if it is not there. Any ideas how I might accomplish this?
There isn't a direct API for pulling information out of the manifest, but there are options.
First, you can just maintain an array of those same URIs in your code, because to change them you'd have to change the manifest and update your package anyway, so you would update the array to match. This would make it easy to check, but increase code maintenance.
Such an array would also let you create a UI in which the user can enter only URIs that will work, e.g. you can offer possibilities from a drop-down list instead of letting the user enter anything.
Second, you can read the manifest XML into a document directly and parse through it to get to the rules. Here's some code that will do that:
var uri = new Windows.Foundation.Uri("ms-appx:///appxmanifest.xml");
var doc;
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file);
}).done(function (text) {
doc = new Windows.Data.Xml.Dom.XmlDocument();
doc.loadXml(text);
var acur = doc.getElementsByTagName("ApplicationContentUriRules");
if (acur !== null) {
var rules = acur[0].getElementsByTagName("Rule");
for (var i = 0; i < rules.length; i++) {
console.log(rules[i].getAttribute("Match") + " - " + rules[i].getAttribute("Type"));
}
}
});
You could probably just get "Rule" tags directly from the root doc, because I don't think anything else in the manifest uses that kind of node, but to future-proof it's better to get the ApplicationContentUriRules first. As you can see, the "Match" attribute is what holds the URI for that rule, but you also need to make sure that "Type" is "include" and not "exclude".

Defalut XmlSiteMapProvider implementation cannot use SiteMap.FindSiteMapNode?

I just upgrade MvcSiteMapProvider from v3 to v4.6.3.
I see the upgrade note indicate:
In general, any reference to System.Web.SiteMap.Provider will need to be updated to MvcSiteMapProvider.SiteMaps.Current
I am trying to get the sitemap node by using:
SiteMaps.Current.FindSiteMapNode(rawUrl)
But it always return null
I looked into the code. In the sitemap it's actually calling the function:
protected virtual ISiteMapNode FindSiteMapNodeFromUrlMatch(IUrlKey urlToMatch)
{
if (this.urlTable.ContainsKey(urlToMatch))
{
return this.urlTable[urlToMatch];
}
return null;
}
It's trying to find a match in the urlTable.
I am using Default implementation of XmlSiteMapProvider .
It define var url = node.GetAttributeValue("url");
siteMapNode.Url = url;
siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");
So if I did not define url or urlResolver attribute in the .sitemap file. These variables a set to empty string, when generate the node.
And when this nodes are passed to AddNode function in SiteMap.
When adding the node
bool isMvcUrl = string.IsNullOrEmpty(node.UnresolvedUrl) && this.UsesDefaultUrlResolver(node);
this code will check if there is url or urlResolver
// Only store URLs if they are clickable and are configured using the Url
// property or provided by a custom URL resolver.
if (!isMvcUrl && node.Clickable)
{
url = this.siteMapChildStateFactory.CreateUrlKey(node);
// Check for duplicates (including matching or empty host names).
if (this.urlTable
.Where(k => string.Equals(k.Key.RootRelativeUrl, url.RootRelativeUrl, StringComparison.OrdinalIgnoreCase))
.Where(k => string.IsNullOrEmpty(k.Key.HostName) || string.IsNullOrEmpty(url.HostName) || string.Equals(k.Key.HostName, url.HostName, StringComparison.OrdinalIgnoreCase))
.Count() > 0)
{
var absoluteUrl = this.urlPath.ResolveUrl(node.UnresolvedUrl, string.IsNullOrEmpty(node.Protocol) ? Uri.UriSchemeHttp : node.Protocol, node.HostName);
throw new InvalidOperationException(string.Format(Resources.Messages.MultipleNodesWithIdenticalUrl, absoluteUrl));
}
}
// Add the URL
if (url != null)
{
this.urlTable[url] = node;
}
Finally no url is add to the urlTable, which result in FindSiteMapNode cannot find anything.
I am not sure if there needs to be specific configuration. Or should I implement custom XmlSiteMapProvider just add the url.
ISiteMapNodeProvider instances cannot use the FindSiteMapNode function for 2 reasons. The first you have already discovered is that finding by URL can only be done if you set the url attribute explicitly in the node configuration. The second reason is that the SiteMapBuilder doesn't add any of the nodes to the SiteMap until all of the ISiteMapNodeProvider instances have completed running, so it would be moot to add the URL to the URL table anyway.
It might help if you explain what you are trying to accomplish.
The ISiteMapNodeProvider classes have complete control over the data that is added to the SiteMapNode instances and they also have access to their parent SiteMapNode instance. This is generally all that is needed in order to populate the data. Looking up another SiteMapNode from the SiteMap object while populating the data is not supported. But as long as the node you are interested in is populated in the same ISiteMapNodeProvider instance, you can just get a reference to it later by storing it in a variable.
Update
Okay, I reread your question and your comment and it now just seems like you are looking in the wrong place. MvcSiteMapProvider v4 is no longer based on Microsoft's SiteMap provider model, so using XmlSiteMapProvider doesn't make sense, as it would sidestep the entire implementation. The only case where this might make sense is if you have a hybrid ASP.NET and ASP.NET MVC application that you want to keep a consitant menu structure between. See Upgrading from v3 to v4.
There are 2 stages to working with the data. The first stage (the ISiteMapBuilder and ISiteMapNodeProvider) loads the data from various sources (XML, .NET attributes, DynamicNodeProviders, and custom implementations of ISiteMapNodeProvider) and adds it to an object graph that starts at the SiteMap object. Much like Microsoft's model, this data is stored in a shared cache and only loaded when the cache expires. This is the stage you have been focusing on and it definitely doesn't make sense to lookup nodes here.
The second stage is when an individual request is made to access the data. This is where looking up data based on a URL might make sense, but there is already a built-in CurrentNode property that finds the node matching the current URL (or more likely the current route since we are dealing with MVC) which in most cases is the best approach to finding a node. Each node has a ParentNode and ChildNodes properties that can be used to walk up or down the tree from there.
In this second stage, you can access the SiteMap data at any point after the Application_Start event such as within a controller action, in one of the built in HTML helpers, an HTML helper template in the /Views/Shared/DisplayTemplates/ directory, or a custom HTML helper. This is the point in the application life cycle which you might call the lines SiteMaps.Current.FindSiteMapNode(rawUrl) or (more likely) SiteMaps.Current.CurrentNode to get an instance of the node so you can inspect its Attributes property (the custom attributes).
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
var currentNode = MvcSiteMapProvider.SiteMaps.Current.CurrentNode;
string permission = currentNode.Attributes.ContainsKey("permission") ? currentNode.Attributes["permission"].ToString() : string.Empty;
string programs = currentNode.Attributes.ContainsKey("programs") ? currentNode.Attributes["programs"].ToString() : string.Empty;
string agencies = currentNode.Attributes.ContainsKey("agencies") ? currentNode.Attributes["agencies"].ToString() : string.Empty;
// Do something with the custom attributes of the About page here
return View();
}
The most common usage of custom attributes is to use them from within a custom HTML helper template. Here is a custom version of the /Views/Shared/DisplayTemplates/SiteMapNodeModel.cshtml template that displays the custom attributes. Note that this template is called recursively by the Menu, SiteMapPath, and SiteMap HTML helpers. Have a look at this answer for more help if HTML helper customization is what you intend to do.
#model MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModel
#using System.Web.Mvc.Html
#using MvcSiteMapProvider.Web.Html.Models
#if (Model.IsCurrentNode && Model.SourceMetadata["HtmlHelper"].ToString() != "MvcSiteMapProvider.Web.Html.MenuHelper") {
<text>#Model.Title</text>
} else if (Model.IsClickable) {
if (string.IsNullOrEmpty(Model.Description))
{
#Model.Title
}
else
{
#Model.Title
}
} else {
<text>#Model.Title</text>
}
#string permission = Model.Attributes.ContainsKey("permission") ? Model.Attributes["permission"].ToString() : string.Empty
#string programs = Model.Attributes.ContainsKey("programs") ? Model.Attributes["programs"].ToString() : string.Empty
#string agencies = Model.Attributes.ContainsKey("agencies") ? Model.Attributes["agencies"].ToString() : string.Empty
<div>#permission</div>
<div>#programs</div>
<div>#agencies</div>

How does one get Drupal's current view/page identifier?

What I am looking for is a page_id/view_id that I can use to identify and style specific pages. I would use the title or the url, but there is a chance that it could change if the a higher-up decides that the page should no longer be called Golf, but rather Tee-Time because he likes it better.
Presumably this identifier would not change if the current page were to be a paged view (page 1,2,3,4...).
One way of solving this is the following. It's depending on the url, so if it changes, so does the class-name.
In my themes template.php I implemented hook_preprocess_page:
function mytheme_preprocess_page(&$vars, $hook) {
$body_classes = array();
$body_classes[] = 'page-' . _get_page_name($_SERVER['REQUEST_URI']);
$vars['body_classes'] = implode(' ', $body_classes);
}
function _get_page_name($request_uri) {
static $numeric_subsection = array(
'/node/' => 'node',
);
$preAlias = $request_uri;
$alias = substr(strrchr($preAlias, "/"), 1);
if (strpos($alias, '?') > -1) {
$alias = substr($alias, 0, strpos($alias, '?'));
}
$page_name = $alias;
if (empty($alias)) {
$page_name = 'start';
}
else if (is_numeric($alias)) {
foreach ($numeric_subsection as $section => $pn) {
if (strpos($preAlias, $section) > -1) {
$page_name = $pn;
}
}
}
return $page_name;
}
Then in the main page-template:
<body class="<?php print $body_classes; ?>">
This isn't a generic solution. So you'll probably have to customize this for your specific needs. It will for example need som tweaking to play nicely with path auto.
This depends a little on how your site is put together (panel pages, view pages, "normal" pages). Essentially, you need to figure out what vars are in scope, and then determine which information in them can be used. To determine what is in scope, you can use print_r(array_keys(get_defined_vars())); and then poke around in the individual vars.
An option is to do something in theme_preprocess_page. One option is to get the page data via page_manager_get_current_page(), poke around in there, and then add body classes as needed. Without knowing what you are doing, you essentially need to print_r the results somewhere, look at what you have, and go from there.

Resources