webhelp file links don't work on Mac Firefox 5

HM5 served us well, now its time has come and it has been replaced... If you have HM5 questions, please post them here.

Moderators: Alexander Halser, Tim Green

Post Reply
Tom Fiddaman
Posts: 5
Joined: Wed May 11, 2011 10:37 pm

webhelp file links don't work on Mac Firefox 5

Unread post by Tom Fiddaman »

I've browsed around with search and can't find a previous report of this.

Our help system links to a number of ancillary files (code for simulation models); these reside in subdirectories of the help location (so that the links work on all platforms). Everything works fine from .chm files on Win machines, and html webhelp on the Mac with Safari. But on the Mac with Firefox 5, the links don't work.

What seems to be happening is the following. A typical link in the generated html looks like:

<span class="f_BodyText"><a href="Models\FunctionExamples\ABS.mdl" class="filelink">ABS.mdl</a> - models from the User's Guide, organized by chapter</span>

Note the backslash in the href.

On Windows, this gets automatically rewritten to an absolute path on the local file system:

file:///C:/Documents%20and%20Settings/Fid/My%20Documents/_Vensim/Documentation/Manual/HTML/Models/FunctionExamples/ABS.mdl

On Safari, the same process works, and again the \ are rewritten as /. But in Firefox 5, the \es in the link don't get rewritten, so the resulting link fails, as in

file:///Volumes/SharedDocs/HTML/Models\FunctionExamples\ABS.mdl

Is there a known workaround for this (other than manually search/replacing the \ each time we build)? Where does the path modification actually happen?

Thanks

Tom
User avatar
Tim Green
Site Admin
Posts: 23181
Joined: Mon Jun 24, 2002 9:11 am
Location: Bruehl, Germany
Contact:

Re: webhelp file links don't work on Mac Firefox 5

Unread post by Tim Green »

Hi Tom,

Actually, it's the other way round: When you enter a path in the file link or Internet link dialog the path is exported exactly as you enter it without conversion. Since the path is being interpreted by a browser it actually needs forward slashes. Windows browsers know about the forward/backward slash dichotomy on Windows and make allowance for it, but browsers on Mac, Linux and and other Unix-based operating systems don't necessarily make this assumption (although some do because of the large number of Windows programmers around...). If you use standard URL forward slashes in your links it should work across all systems. 8)
Regards,
Tim (EC Software Documentation & User Support)

Private support:
Please do not email or PM me with private support requests -- post to the forum directly.
Tom Fiddaman
Posts: 5
Joined: Wed May 11, 2011 10:37 pm

Re: webhelp file links don't work on Mac Firefox 5

Unread post by Tom Fiddaman »

Ahh ... that makes sense. I think I must have been thinking in the wrong file system paradigm when I started adding directory nesting to my links manually, because the Edit Hyperlink dialog actually doesn't reflect folder hierarchy when you use its browse button. Thanks!
Tom Fiddaman
Posts: 5
Joined: Wed May 11, 2011 10:37 pm

Re: webhelp file links don't work on Mac Firefox 5

Unread post by Tom Fiddaman »

I may have spoken too soon ... it seems that / doesn't work for nested link references in .chm ?
User avatar
Tim Green
Site Admin
Posts: 23181
Joined: Mon Jun 24, 2002 9:11 am
Location: Bruehl, Germany
Contact:

Re: webhelp file links don't work on Mac Firefox 5

Unread post by Tim Green »

Tom Fiddaman wrote:I may have spoken too soon ... it seems that / doesn't work for nested link references in .chm ?
It doesn't work in CHM because Microsoft's CHM system has a known "relative paths bug" that has been uncorrected since the CHM system was released with Windows 98. You can fix this problem with my relative paths bug correction script. 8) Note that this is designed for use with CHM which is Windows only, because only CHM has this problem, so it uses backslashes. You will need to insert two versions of each link with conditional text tags: One with forward slashes for HTML and one with backslashes for CHM., :wink:
Regards,
Tim (EC Software Documentation & User Support)

Private support:
Please do not email or PM me with private support requests -- post to the forum directly.
Tom Fiddaman
Posts: 5
Joined: Wed May 11, 2011 10:37 pm

Re: webhelp file links don't work on Mac Firefox 5

Unread post by Tom Fiddaman »

Thanks again. I'm good to go now. Fortunately I don't need path access outside the help folder, just nested within it. So, all I had to do was insert conditional text to create \ links for chm and / links for webhelp.

I wrote a bit of Java to process all my XML topics, making a single link with \ or / into conditional text with appropriate slashes for each build. I'm sure it's neither the best tool nor the best code for this, but here it is for what it's worth:

Code: Select all

package conditionalhelplinks;

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.commons.io.FileUtils;
import java.util.Date;
import java.text.SimpleDateFormat;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import org.w3c.dom.NamedNodeMap;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

/**
 *
 * @author Fid
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        // location of topics to be made conditional
        File dir = new File("c:\\Documents and Settings\\Fid\\My Documents\\_vensim\\documentation\\manual\\topics");
        
        // first copy all the originals to a directory for backup
        File origDir = new File(dir.getAbsolutePath().concat("\\orig"));

        // filter for xml files (normally this is all the Topics directory contains anyway, I think)
        FileFilter fileFilter = new FileFilter() {
            public boolean accept(File file) {
                return file.getName().endsWith(".xml");
            }
        };
        File[] files = dir.listFiles(fileFilter);

        if (files == null) {
            // Either dir does not exist or is not a directory
            System.out.println("null file list for " + dir.getAbsolutePath());
        } else {
            System.out.println("processing " + files.length + " files");

            // cutoff date for processing xml files (only edit files newer than this date)
            Long c = new Long("1308930874109");
            long cutoff = c.longValue();

            // count of files processed
            int n = 0;

            // iterate over file list
            for (int i = 0; i < files.length; i++) {

                // Get filename of file or directory
                File file = files[i];
                String fname = file.getName();

                // check date and process if needed
                long mod = file.lastModified();
                if (mod > cutoff) {
                    // increment file count
                    n++;
                    
                    Date modDate = new Date(mod);
                    SimpleDateFormat sdf = new SimpleDateFormat("EEEE yyyy/MM/dd hh:mm:ss aa zz : zzzzzz");
                    System.out.println(n + " " + fname + " " + mod + " " + sdf.format(modDate));

                    try {
                        FileUtils.copyFileToDirectory(file, origDir, true); // make backup

                        // parse the xml
                        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                        Document doc = docBuilder.parse(file);

                        // get the list of nodes that are links
                        NodeList links = doc.getElementsByTagName("link");

                        // iterate over links
                        for (int j = 0; j < links.getLength(); j++) {
                            Node node = links.item(j);
                            System.out.println(node.toString());
                            //Node parent = node.getParentNode();
                            //System.out.println("\t^ "+parent.toString());
                            
                            // check whether a node has already been made conditional (in which case previous node should be a conditional-text)
                            Node prev = node.getPreviousSibling();
                            if (prev == null) { // no previous sibling
                                hrefMakeConditional(node, doc);
                            } else {
                                System.out.println("\t<- " + prev.toString() + " " + prev.getNodeName());
                                if ( ! prev.getNodeName().equalsIgnoreCase("conditional-text")) { // skip items that are already conditional
                                    // TODO: conceivably this could go wrong if a link node has a prior node that is an ENDIF or some other condition, but ignore this potential hazard
                                    hrefMakeConditional(node, doc);
                                }
                            }
                        }

                        // write output
                        Transformer transformer = TransformerFactory.newInstance().newTransformer();
                        //transformer.setOutputProperty(OutputKeys.INDENT, "yes");

                        //initialize StreamResult with File object to save to file
                        File dest = new File(dir.getAbsolutePath() + "\\mod\\" + fname); // output goes to a "mod" subdirectory - at end of process, files in mod should be copied up to replace the originals in Topics
                        StreamResult result = new StreamResult(dest);
                        DOMSource source = new DOMSource(doc);
                        transformer.transform(source, result);



                    } catch (TransformerException ex) {
                        ex.printStackTrace();
                    } catch (ParserConfigurationException ex) {
                        ex.printStackTrace();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    } catch (SAXException ex) {
                        ex.printStackTrace();
                    }

                }


            }
        }
    }

    static void hrefMakeConditional(Node node, Document doc) {
        
        // TODO could also check whether there are any \ / to worry about at all, before processing
        
        if (checkFileLink(node)) {
            // add IF conditional
            Element ifElm = doc.createElement("conditional-text");
            ifElm.setAttribute("type", "IF");
            ifElm.setAttribute("value", "CHM");
            node.getParentNode().insertBefore(ifElm, node);

            // give this node backslashes for .chm format
            pathSetSeparator(node, false);

            // add ELSE conditional
            Element elseElm = doc.createElement("conditional-text");
            elseElm.setAttribute("type", "ELSE");
            insertAfter(node, elseElm);

            // make a clone with frontslashes for webhelp html
            Node webNode = node.cloneNode(true);
            pathSetSeparator(webNode, true);
            insertAfter(elseElm, webNode);

            // add ENDIF
            Element endElm = doc.createElement("conditional-text");
            endElm.setAttribute("type", "END");
            insertAfter(webNode, endElm);
        }
    }

    static void insertAfter(Node nexist, Node nnew) {
        //System.out.println("inserting " + nnew.toString() + " after " + nexist.toString() + " which has sibling " + nexist.getNextSibling());
        if (nexist.getNextSibling() == null) {
            nexist.getParentNode().appendChild(nnew); // no next sibling; make it last in list
        } else {
            nexist.getParentNode().insertBefore(nnew, nexist.getNextSibling()); // insert before next sibling
        }
    }

    static void pathSetSeparator(Node node, boolean frontSlash) {
        // get the href from the link and change all /\ to a consistent form
        // note that this assumes that links don't contain any quoted \/ or escaped \\ or other confusing slashy stuff
        if (node.hasAttributes()) {
            NamedNodeMap attribs = node.getAttributes();
            Node type = attribs.getNamedItem("type");
            if (type != null) {
                if (type.getNodeValue().equalsIgnoreCase("filelink")) {
                    System.out.println("\t" + node.toString() + "-> conditional");
                    Node href = attribs.getNamedItem("href"); // TODO: check for null
                    String hrefString = href.getNodeValue();
                    if (frontSlash) {
                        href.setNodeValue(hrefString.replace('\\', '/'));
                    } else {
                        href.setNodeValue(hrefString.replace('/', '\\'));
                    }
                } else {
                    System.out.println("\t\tnot a filelink");
                }

            } else {
                System.out.println("\t\tERROR! null type");
            }
        } else {
            System.out.println("\t\tERROR! no attributes");
        }
    }

    static boolean checkFileLink(Node node) {
        // check whether the node is a 'filelink' (don't want to process 'topiclink' or other links)
        if (node.hasAttributes()) {
            NamedNodeMap attribs = node.getAttributes();
            Node type = attribs.getNamedItem("type");
            if (type != null) {
                if (type.getNodeValue().equalsIgnoreCase("filelink")) {
                    return true;
                }
            }
        }
        return false;
    }
}
User avatar
Tim Green
Site Admin
Posts: 23181
Joined: Mon Jun 24, 2002 9:11 am
Location: Bruehl, Germany
Contact:

Re: webhelp file links don't work on Mac Firefox 5

Unread post by Tim Green »

Hi Tom,

Great to hear, and thanks for posting the Java listing. You might want to post it in the Templates and Utilities section as well. Things like this tend to "go under" quite quickly in the general forum and it's a nice resource for others to use. :)
Regards,
Tim (EC Software Documentation & User Support)

Private support:
Please do not email or PM me with private support requests -- post to the forum directly.
Post Reply