/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * muCommander is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mucommander.bookmark; import com.mucommander.auth.CredentialsManager; import com.mucommander.auth.CredentialsMapping; import com.mucommander.commons.file.Credentials; import com.mucommander.commons.file.FileURL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParserFactory; import java.io.InputStream; import java.net.MalformedURLException; /** * This class takes care of parsing the bookmarks XML file and adding parsed {@link Bookmark} instances to {@link BookmarkManager}. * * @author Maxence Bernard */ class BookmarkParser extends DefaultHandler implements BookmarkConstants { private static final Logger LOGGER = LoggerFactory.getLogger(BookmarkParser.class); /** Variable used for XML parsing */ private String bookmarkName; /** Variable used for XML parsing */ private String bookmarkLocation; /** Variable used for XML parsing */ private StringBuilder characters; /** Receives bookmarks events. */ private BookmarkBuilder builder; /** muCommander version that was used to write the bookmarks file */ private String version; /** * Creates a new BookmarkParser instance. */ public BookmarkParser() {} /** * Parses the given XML bookmarks file. Should only be called by BookmarkManager. */ void parse(InputStream in, BookmarkBuilder builder) throws Exception { this.builder = builder; characters = new StringBuilder(); SAXParserFactory.newInstance().newSAXParser().parse(in, this); } /** * Returns the muCommander version that was used to write the bookmarks file, <code>null</code> if it is unknown. * <p> * Note: the version attribute was introduced in muCommander 0.8.4. * </p> * * @return the muCommander version that was used to write the bookmarks file, <code>null</code> if it is unknown. */ public String getVersion() { return version; } /* ------------------------ */ /* ContentHandler methods */ /* ------------------------ */ @Override public void startDocument() throws SAXException { try {builder.startBookmarks();} catch(BookmarkException e) {throw new SAXException(e);} } @Override public void endDocument() throws SAXException { try {builder.endBookmarks();} catch(BookmarkException e) {throw new SAXException(e);} } /** * Method called when some PCDATA has been found in an XML node. */ @Override public void characters(char[] ch, int start, int length) {characters.append(ch, start, length);} /** * Notifies the parser that a new XML node has been found. */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { characters.setLength(0); if(qName.equals(ELEMENT_ROOT)) { version = attributes.getValue(ATTRIBUTE_VERSION); } else if(qName.equals(ELEMENT_BOOKMARK)) { // Reset parsing variables bookmarkName = null; bookmarkLocation = null; } } /** * Notifies the parser that an XML node has been closed. */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(qName.equals(ELEMENT_BOOKMARK)) { if(bookmarkName == null || bookmarkLocation == null) { LOGGER.info("Missing value, bookmark ignored: name=" + bookmarkName + " location=" + bookmarkLocation); return; } try {builder.addBookmark(bookmarkName, bookmarkLocation);} catch(BookmarkException e) {throw new SAXException(e);} } else if(qName.equals(ELEMENT_NAME)) { bookmarkName = characters.toString().trim(); } else if(qName.equals(ELEMENT_LOCATION)) { bookmarkLocation = characters.toString().trim(); } // Note: url element has been deprecated in 0.8 beta3 but is still checked against for upward compatibility. else if(qName.equals(ELEMENT_URL)) { // Until early 0.8 beta3 nightly builds, credentials were stored directly in the bookmark's url. // Now bookmark locations are free of credentials, these are stored in a dedicated credentials file where // the password is encrypted. try { FileURL url = FileURL.getFileURL(characters.toString().trim()); Credentials credentials = url.getCredentials(); // If the URL contains credentials, import them into CredentialsManager and remove credentials // from the bookmark's location if(credentials!=null) { CredentialsManager.addCredentials(new CredentialsMapping(credentials, url, true)); bookmarkLocation = url.toString(false); } else { bookmarkLocation = characters.toString().trim(); } } catch(MalformedURLException e) { bookmarkLocation = characters.toString().trim(); } } } }