Jsoup Modify Links - spring

I am, very new to spring and jsoup... I am using jsoup to parse an html file and copy some text inside a div tag and displaying it on my page. Now i am trying to modify the links and add exit.do to log the users out of the server. I have tried many different approach and my links dont work :( has anyone dealt with this link update before? any help is appriciated.
here is my code.
Thanks a lot.
Lola
modelMap = referenceData( request, modelMap);
modelMap.put("externalUrl", externalUrlMap.get( request.getServletPath() ));
modelMap.put("elementId", elementIdMap.get( request.getServletPath() ));
/** Pass the url map to a string */
String url = (String) externalUrlMap.get( request.getServletPath() );
/** Pass the div map to a string */
String eleId = (String) elementIdMap.get( request.getServletPath() );
/** Retrieve and parse the document using Jsoup*/
//URL externalUrl = new URL(url);
//Document document = Jsoup.parse(externalUrl, 10000);
File internalFile = new File(url);
Document document = Jsoup.parse(internalFile, "UTF-8");
/** Clean the document to prevent XSS only include tags and style below */
//document = new Cleaner(Whitelist.basic().addTags("div", "em", "h1", "h2").addAttributes("div","class", "style")).clean(document);
/** Select privactText tags from the id */
Element divContent = document.select(eleId).first();
/** Returned the text inside the div tag */
String parsedExternalContent = divContent.html();
/** Get all links inside div tag */
Elements links = divContent.select("a[href]");
String exitUrl = "/exit?logout=true&uri=";
/** Loop through the links and if the links are relative path add the exit.do to the link */
for (Element link : links) {
if (!link.attr("href").toLowerCase().startsWith("http://")) {
String urltext = link.attr("href");
String exitText = "/exit?logout=true&uri=";
...
}
}
modelMap.addAttribute("parsedExternalContent", parsedExternalContent);
return new ModelAndView ("externalParserContent", modelMap);

This is the way i did it when i needed to re-write an original string with "encoded" url:
Document doc = getHtmlDocumentFromString(htmlOnly);
Elements links = doc.select("a[href]");
/**
* since we would want to track link index per click - iterate links in the old fashion way (Elements is a List<Element>)
*/
for(int linkIndexTopToBottom = 0; linkIndexTopToBottom < links.size(); linkIndexTopToBottom++){
try{
Element link = links.get(linkIndexTopToBottom);
if (!UriUtils.isValidUrl(link.attr("href")))
continue;
...
link.attr("href",<NEW URL>);
}catch (MalformedURLException exception){
log.debug("Provided URL was not valid: " + links.get(linkIndexTopToBottom).attr("abs:href") + ", skipping link re-write");
}
}
return doc;
As you can see you need to set the attribute like:
link.attr("href", <NEW URL>);
since that part was missing from your post, i were not sure whether you do it or not
EDIT
The appending would be exactly the same idea:
link.attr("href", link.attr("href") + "<what you need to append with>");
The bottom line is you need to set href attribute to a new value
Example from the jSoup cook book

Related

How to get "Repro Steps" of a list of work items?

My team has been using VSTS for 8 months. Now, Our customer is asking to get "Repro Steps" of the work items in VSTS.
Is there any way to get the content of "Repro Steps" without the HTML format?
No, because the Repro Steps value is the rich text that can contain image etc…. So, the value is incorrect if just return the data without HTML format.
However, you can remove HTML tag programing.
Simple code:
public static string StripHTML(string input)
{
return Regex.Replace(input, "<.*?>", String.Empty);
}
var u = new Uri("[collection URL]"");
VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.WindowsCredential(new NetworkCredential("[user name]", "[password]")));
var connection = new VssConnection(u, c);
var workitemClient = connection.GetClient<WorkItemTrackingHttpClient>();
var workitem = workitemClient.GetWorkItemAsync(96).Result;
object repoValue = workitem.Fields["Microsoft.VSTS.TCM.ReproSteps"];
string repoValueWithOutformat = StripHTML(repoValue.ToString());

eclipse scout image change

I am trying to change image inside Image view.
I know that getTestImageField().setImageId(Icons.Logo); would not work, because it would not refresh renderer.
Because I need to use setImage(), I need a way to get Image from Icons class.
As Patrick suggested I try
final IconProviderService provider = SERVICES.getService(IconProviderService.class);
final IconSpec ic = provider.getIconSpec(AbstractIcons.StatusError);
final byte[] content = ic.getContent();
but my problem is that ic is always null.
While I debug this I notice that inside IconProviderService.class in line 57 :
#Override
protected URL findResource(String fullPath) {
URL[] entries = FileLocator.findEntries(m_hostBundle, new Path(fullPath));
if (entries != null && entries.length > 0) {
URL url = entries[entries.length - 1];
if (LOG.isDebugEnabled()) {
LOG.debug("find image " + fullPath + " in bundle " + m_hostBundle.getSymbolicName() + "->" + url);
}
return url;
}
return null;
}
URL[] entries is always empty no matter witch icon I try to present.
After further debugging I found out that FileLocator tries to find fragments from bundle, and then look for the path inside this fragments. (line 242)
Bundle[] fragments = activator.getFragments(b);
but Bundle[] fragments is always null.
Normally my bundle b is (Bundle) EquinoxBundle : org.eclipse.scout.rt.ui.rap.mobile_4.0.100.20140829-1424.
I want to try with different bundle so I do :
final BundleContext context = Activator.getDefault().getBundle().getBundleContext();
for (final Bundle b : context.getBundles()) {
final IconProviderService provider = SERVICES.getService(IconProviderService.class);
provider.setHostBundle(b);
final IconSpec ic = provider.getIconSpec(AbstractIcons.StatusError);
if (ic != null) {
final byte[] content = ic.getContent();
imageField().setImage(content);
}
}
but fragments (from above code) is always null.
You can obtain the image content (byte[]) that you can set on the image field as follows:
IconProviderService provider = SERVICES.getService(IconProviderService.class);
byte[] content = provider.getIconSpec(Icons.YourIconName).getContent();
getImageField().setImage(content);
I quickly checked it and it works for me.
Please ensure that the icon is available and you set up the icon provider service as explained in this Wiki Article

How to retrieve photo previews in app.net

When I have an app.net url like https://photos.app.net/5269262/1 - how can I retrieve the image thumbnail of the post?
Running a curl on above url shows a redirect
bash-3.2$ curl -i https://photos.app.net/5269262/1
HTTP/1.1 301 MOVED PERMANENTLY
Location: https://alpha.app.net/pfleidi/post/5269262/photo/1
Following this gives a html page that contains the image in a form of
img src='https://files.app.net/1/60621/aWBTKTYxzYZTqnkESkwx475u_ShTwEOiezzBjM3-ZzVBjq_6rzno42oMw9LxS5VH0WQEgoxWegIDKJo0eRDAc-uwTcOTaGYobfqx19vMOOMiyh2M3IMe6sDNkcQWPZPeE0PjIve4Vy0YFCM8MsHWbYYA2DFNKMdyNUnwmB2KuECjHqe0-Y9_ODD1pnFSOsOjH' data-full-width='2048' data-full-height='1536'
Inside a larger block of <div>tags.
The files api in app.net allows to retrieve thumbnails but I somehow don't get the link between those endpoints and above urls.
The photos.app.net is just a simple redirecter. It is not part of the API proper. In order to get the thumbnail, you will need to fetch the file directly using the file fetch endpoint and the file id (http://developers.app.net/docs/resources/file/lookup/#retrieve-a-file) or fetch the post that the file is included in and examine the oembed annotation.
In this case, you are talking about post id 5269262 and the URL to fetch that post with the annotation is https://alpha-api.app.net/stream/0/posts/5269262?include_annotations=1 and if you examine the resulting json document you will see the thumbnail_url.
For completeness sake I want to post the final solution for me here (in Java) -- it builds on the good and accepted answer of Jonathon Duerig :
private static String getAppNetPreviewUrl(String url) {
Pattern photosPattern = Pattern.compile(".*photos.app.net/([0-9]+)/.*");
Matcher m = photosPattern.matcher(url);
if (!m.matches()) {
return null;
}
String id = m.group(1);
String streamUrl = "https://alpha-api.app.net/stream/0/posts/"
+ id + "?include_annotations=1";
// Now that we have the posting url, we can get it and parse
// for the thumbnail
BufferedReader br = null;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) new URL(streamUrl).openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(false);
urlConnection.setRequestProperty("Accept","application/json");
urlConnection.connect();
StringBuilder builder = new StringBuilder();
br = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line=br.readLine())!=null) {
builder.append(line);
}
urlConnection.disconnect();
// Parse the obtained json
JSONObject post = new JSONObject(builder.toString());
JSONObject data = post.getJSONObject("data");
JSONArray annotations = data.getJSONArray("annotations");
JSONObject annotationValue = annotations.getJSONObject(0);
JSONObject value = annotationValue.getJSONObject("value");
String finalUrl = value.getString("thumbnail_large_url");
return finalUrl;
} .......

Getting a TinyMCE dropdown image list in an MVC3 application

I am trying to get an MVC3 app to feed TinyMCE with an external image list javascript file. I have TinyMCE set up so that if I use a static image list file, I get the image list, so I know that part works. But since I need to dynamically create the image list per user, I need something more flexible than a static file. It is down to providing the javascript from the following controller action:
public JavaScriptResult TinyMCEImageList(int id)
{
ListHelper lh = new ListHelper();
string js = "var tinyMCEImageList = new Array(\r\n" + "// Name, URL\r\n";
Dictionary<string, string> dict = lh.GetPetImageURLs(id);
int i = dict.Count();
foreach (var item in dict)
{
js += "['" + item.Key + "', '" + item.Value + "']";
if (i > 1)
{
js += ",\r\n";
}
i--;
}
js += "\r\n);";
return JavaScript(js);
}
The ListHelper.GetPetImageURLs() returns a dictionary object, which is simply a convenient way to hold the caption and URL of each image. When I call this controller from the browser, with the appropriate id parameter, I get what I would think is a workable JS file. In fact, such results are what I used to create the static file I used to test the TinyMCE image list setup, and that got me an actual dropdown image list.
Here is my TinyMCE setup. This is inside the view containing a TinyMCE instance:
tinyMCE.init({
mode: "textareas",
theme: "advanced",
plugins: "lists,pagebreak,style,table,inlinepopups,advhr,advimage,preview,searchreplace,print,paste,visualchars,nonbreaking",
theme_advanced_buttons1: "newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,forecolor,backcolor,image",
theme_advanced_buttons3: "tablecontrols,|,visualaid,|,sub,sup,|,advhr,|,preview,print,|,visualchars,nonbreaking,template,blockquote,pagebreak",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
theme_advanced_statusbar_location: "bottom",
theme_advanced_resizing: true,
external_image_list_url: "/InstructionDocument/TinyMCEImageList/#ViewBag.PetID"
});
The #ViewBag.PetID is being used elsewhere, so I know it is valid. Even if I hardcode this value, or specifically point to the controller action, I still do not get a dropdown list of images. I'm sure there's something simple I'm missing; can someone point out to me what it is (or at least give me some reasonable guidance)?
[EDIT]
The output from the TinyMCEImageList() action follows:
var tinyMCEImageList = new Array(
// Name, URL
['System Guinea Pig - 4', 'http://www.remindapet.com/Content/images/galler/1_4_970BB64F7C1A4375AF5722B8A62C8708.jpg'],
['System Guinea Pig - 5', 'http://www.remindapet.com/Content/images/gallery/1_4_CBA0D3DDBBED41C583A6E6C46FC9DADF.jpg']
);
Also, here are the headers for the above javascript return from the action:
Server ASP.NET Development Server/10.0.0.0
Date Fri, 23 Dec 2011 00:14:31 GMT
X-AspNet-Version 4.0.30319
X-AspNetMvc-Version 3.0
Cache-Control private
Content-Type application/x-javascript; charset=utf-8
Content-Length 292
Connection Close
So, the action really is returning a JavascriptResult. I just haven't been able to come up with how to get TinyMCE to see it.
Thanks!
Instead of rendering an javascriptresult, create a js file while you are rendering the page.
Controller
public ActionResult Index()
{
MakeJSFile();
return View();
}
MakeJSFile() function will create the jsfile we need, then the page will be rendered.
MakeJSFile() function
public void MakeJSFile()
{
#region declare
var imgPath = Server.MapPath("~/Content/images/gallery/");
var jsPath = Server.MapPath("~/Scripts/image_list.js");
List<string> fileList = populateList(imgPath, ".jpg");
#endregion
#region build jsfile
string content = "var tinyMCEImageList = new Array(";
foreach (var item in fileList)
{
content += "[\"" + item + "\", \"/Content/img/" + item + "\"]";
if (item != fileList.Last())
content += ",";
}
content += ");";
#endregion
#region create file
StreamWriter sw = new StreamWriter(jsPath, false);
sw.Write(content);
sw.Close();
#endregion
}
First declare the path for the directory where the images is, and also the path of the jsfile. Then create a list that contains the filenames and populate it(with populateList function).
Then create a string to build the jsfile.
After that create the file in you server.
You only need to do one more thing, create the populateList function.
PopulateList function
public List<string> populateList(string path, params string[] extensions)
{
List<string> list = new List<string>();
FileInfo fi = new FileInfo(path);
DirectoryInfo di = fi.Directory;
FileSystemInfo[] fsi = di.GetFiles();
foreach (FileSystemInfo info in fsi)
foreach (var ext in extensions)
if (info.Extension == ext)
list.Add(info.Name);
return list;
}
This function requires the path to the directory and file extensions.
If you want a specific list, just change this function.
One more thing, don't forget to change the value of external_image_list_url
tinyMCE.init({
...
external_image_list_url: "/Scripts/image_list.js"
});

Wicket: How can I rerender the current form without losing existing input?

I have a form with a combobox/drop down to select the user language. If the user changes the language, I'd like to update all the labels but leave the input elements alone.
In jQuery, I'd request a list of label IDs and the new texts via JSON and then use a loop like this:
var texts = {[ {id:'nameLabel', text:'First Name'}, {id:'familyLabel', text:'Family Name'} ]};
for( var i=0; i<texts.length; i++) {
var item = texts[i];
$('#'+item.id).text(item.text);
}
That would update all the labels without modifying anything else. How do I do this in Wicket?
[EDIT] What I tried:
DropDownChoice<Locale> ddc = new DropDownChoice<Locale>(...);
ddc.add( new AjaxFormComponentUpdatingBehavior("onchange") {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate( AjaxRequestTarget target ) {
getSession().setLocale( language );
for( MarkupContainer label : labels ) {
target.addComponent( label );
}
}
});
This does change the labels but it also renders all the input fields again. I found no way to access the current values of the input fields.
[EDIT2] The list of labels is created like so:
StringResourceModel usernameLabel = new StringResourceModel("usernameLabel", this, new Model<ValueMap>(map));
labels.add(add(new Label("usernameLabel", usernameLabel)));
This is wrong:
labels.add(add(new Label("usernameLabel", usernameLabel)));
You're not adding Label instances to 'labels', it's repeatedly adding the container you are adding it to (probably the Page instance). The method 'add()' doesn't return the component being added, it returns the container you are adding the components into.
Try changing it to:
Label label = new Label("usernameLabel", usernameLabel);
add(label);
labels.add(label);

Resources