/** * DOCUMENT ME! * * @return DOCUMENT ME! * @throws CloneNotSupportedException DOCUMENT ME! */ @Override protected Object clone() throws CloneNotSupportedException { final MagicMatcher clone = new MagicMatcher(); clone.setMatch((MagicMatch) this.match.clone()); final Iterator<MagicMatcher> i = this.subMatchers.iterator(); final ArrayList<MagicMatcher> sub = new ArrayList<MagicMatcher>(); while (i.hasNext()) { final MagicMatcher m = i.next(); sub.add((MagicMatcher) m.clone()); } clone.setSubMatchers(sub); return clone; }
/** * DOCUMENT ME! * * @param uri DOCUMENT ME! * @param localName DOCUMENT ME! * @param qname DOCUMENT ME! * @throws SAXException DOCUMENT ME! */ public void endElement(String uri, String localName, String qname) throws SAXException { log.debug("endElement()"); log.debug("endElement(): localName is '" + localName + "'"); // determine which tag these chars are for and save them if (isMimeType) { isMimeType = false; match.setMimeType(finalValue); log.debug("characters(): setting mimetype to '" + finalValue + "'"); } else if (isExtension) { isExtension = false; match.setExtension(finalValue); log.debug("characters(): setting extension to '" + finalValue + "'"); } else if (isDescription) { isDescription = false; match.setDescription(finalValue); log.debug("characters(): setting description to '" + finalValue + "'"); } else if (isTest) { isTest = false; match.setTest(convertOctals(finalValue)); log.debug("characters(): setting test to '" + convertOctals(finalValue) + "'"); } else { // do nothing } finalValue = ""; // need to save the current matcher here if it is filled out enough and // we have an /matcher if (localName.equals("match")) { // FIXME - make sure the MagicMatcher isValid() test works if (matcher.isValid()) { // set the collected properties on this matcher match.setProperties(properties); // add root match if (stack.size() == 0) { log.debug("endElement(): adding root matcher"); matchers.add(matcher); } else { // we need to add the match to it's parent which is on the // stack log.debug("endElement(): adding sub matcher"); MagicMatcher m = (MagicMatcher) stack.get(stack.size() - 1); m.addSubMatcher(matcher); } } else { // don't add invalid matchers log.info("endElement(): not adding invalid matcher '" + match.getDescription() + "'"); } matcher = null; properties = null; // restore matcher from the stack if we have an /matcher-list } else if (localName.equals("match-list")) { if (stack.size() > 0) { log.debug("endElement(): popping from the stack"); matcher = (MagicMatcher) stack.get(stack.size() - 1); // pop from the stack stack.remove(matcher); } } else if (localName.equals("mimetype")) { isMimeType = false; } else if (localName.equals("extension")) { isExtension = false; } else if (localName.equals("description")) { isDescription = false; } else if (localName.equals("test")) { isTest = false; } }
/** * DOCUMENT ME! * * @param uri DOCUMENT ME! * @param localName DOCUMENT ME! * @param qname DOCUMENT ME! * @param attributes DOCUMENT ME! * @throws SAXException DOCUMENT ME! */ public void startElement(String uri, String localName, String qname, Attributes attributes) throws SAXException { log.debug("startElement()"); log.debug("startElement(): localName is '" + localName + "'"); // create a new matcher if (localName.equals("match")) { log.debug("startElement(): creating new matcher"); // match to hold data match = new MagicMatch(); // our matcher matcher = new MagicMatcher(); matcher.setMatch(match); } // these are subelements of matcher, but also occur elsewhere if (matcher != null) { if (localName.equals("mimetype")) { isMimeType = true; } else if (localName.equals("extension")) { isExtension = true; } else if (localName.equals("description")) { isDescription = true; } else if (localName.equals("test")) { isTest = true; int length = attributes.getLength(); for (int i = 0; i < length; i++) { String attrLocalName = attributes.getLocalName(i); String attrValue = attributes.getValue(i); if (attrLocalName.equals("offset")) { if (!attrValue.equals("")) { match.setOffset(new Integer(attrValue).intValue()); log.debug("startElement(): setting offset to '" + attrValue + "'"); } } else if (attrLocalName.equals("length")) { if (!attrValue.equals("")) { match.setLength(new Integer(attrValue).intValue()); log.debug("startElement(): setting length to '" + attrValue + "'"); } } else if (attrLocalName.equals("type")) { match.setType(attrValue); log.debug("startElement(): setting type to '" + attrValue + "'"); } else if (attrLocalName.equals("bitmask")) { if (!attrValue.equals("")) { match.setBitmask(attrValue); log.debug("startElement(): setting bitmask to '" + attrValue + "'"); } } else if (attrLocalName.equals("comparator")) { match.setComparator(attrValue); log.debug("startElement(): setting comparator to '" + attrValue + "'"); } } } else if (localName.equals("property")) { int length = attributes.getLength(); String name = null; String value = null; for (int i = 0; i < length; i++) { String attrLocalName = attributes.getLocalName(i); String attrValue = attributes.getValue(i); if (attrLocalName.equals("name")) { if (!attrValue.equals("")) { name = attrValue; } } else if (attrLocalName.equals("value")) { if (!attrValue.equals("")) { value = attrValue; } } } // save the property to our map if ((name != null) && (value != null)) { if (properties == null) { properties = new HashMap(); } if (!properties.containsKey(name)) { properties.put(name, value); log.debug("startElement(): setting property '" + name + "'='" + value + "'"); } else { log.debug("startElement(): not setting property '" + name + "', duplicate key"); } } } else if (localName.equals("match-list")) { log.debug("startElement(): found submatcher list"); // this means we are processing a child match, so we need to push // the existing match on the stack log.debug("startElement(): pushing current matcher to stack"); stack.add(matcher); } else { // we don't care about this type } } }
/** * test to see if this match or any submatches match * * @param data the data that should be used to test the match * @param onlyMimeMatch DOCUMENT ME! * @return the deepest magic match object that matched * @throws IOException DOCUMENT ME! * @throws UnsupportedTypeException DOCUMENT ME! */ public MagicMatch test(final byte[] data, final boolean onlyMimeMatch) throws IOException, UnsupportedTypeException { final int offset = this.match.getOffset(); this.match.getDescription(); final String type = this.match.getType(); this.match.getMimeType(); int length = 0; if (type.equals("byte")) { // $NON-NLS-1$ length = 1; } else if (type.equals("short") || type.equals("leshort") || type.equals("beshort")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ length = 4; } else if (type.equals("long") || type.equals("lelong") || type.equals("belong")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ length = 8; } else if (type.equals("string")) { // $NON-NLS-1$ length = this.match.getTest().capacity(); } else if (type.equals("regex")) { // $NON-NLS-1$ // FIXME - something wrong here, shouldn't have to subtract 1??? length = data.length - offset - 1; if (length < 0) { length = 0; } } else if (type.equals("detector")) { // $NON-NLS-1$ // FIXME - something wrong here, shouldn't have to subtract 1??? length = data.length - offset - 1; if (length < 0) { length = 0; } } else { throw new UnsupportedTypeException("unsupported test type " + type); // $NON-NLS-1$ } final byte[] buf = new byte[length]; if (offset + length < data.length) { System.arraycopy(data, offset, buf, 0, length); MagicMatch match1 = null; MagicMatch submatch = null; if (testInternal(buf)) { // set the top level match to this one match1 = getMatch(); // set the data on this match if (onlyMimeMatch == false && this.subMatchers != null && this.subMatchers.size() > 0) { for (int i = 0; i < this.subMatchers.size(); i++) { final MagicMatcher m = this.subMatchers.get(i); if ((submatch = m.test(data, false)) != null) { match1.addSubMatch(submatch); } } } } return match1; } return null; }
/** * test to see if this match or any submatches match * * @param f the file that should be used to test the match * @param onlyMimeMatch DOCUMENT ME! * @return the deepest magic match object that matched * @throws IOException DOCUMENT ME! * @throws UnsupportedTypeException DOCUMENT ME! */ public MagicMatch test(final File f, final boolean onlyMimeMatch) throws IOException, UnsupportedTypeException { final int offset = this.match.getOffset(); this.match.getDescription(); final String type = this.match.getType(); this.match.getMimeType(); final RandomAccessFile file = new RandomAccessFile(f, "r"); // $NON-NLS-1$ int length = 0; if (type.equals("byte")) { // $NON-NLS-1$ length = 1; } else if (type.equals("short") || type.equals("leshort") || type.equals("beshort")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ length = 4; } else if (type.equals("long") || type.equals("lelong") || type.equals("belong")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ length = 8; } else if (type.equals("string")) { // $NON-NLS-1$ length = this.match.getTest().capacity(); } else if (type.equals("regex")) { // $NON-NLS-1$ length = (int) file.length() - offset; if (length < 0) { length = 0; } } else if (type.equals("detector")) { // $NON-NLS-1$ length = (int) file.length() - offset; if (length < 0) { length = 0; } } else { file.close(); throw new UnsupportedTypeException( "unsupported test type '" + type + "'"); // $NON-NLS-1$ //$NON-NLS-2$ } // we know this match won't work since there isn't enough data for the test if (length > file.length() - offset) { file.close(); return null; } final byte[] buf = new byte[length]; file.seek(offset); int bytesRead = 0; int size = 0; boolean done = false; while (!done) { size = file.read(buf, 0, length - bytesRead); if (size == -1) { file.close(); throw new IOException("reached end of file before all bytes were read"); // $NON-NLS-1$ } bytesRead += size; if (bytesRead == length) { done = true; } } MagicMatch match1 = null; MagicMatch submatch = null; if (testInternal(buf)) { // set the top level match to this one match1 = getMatch(); // set the data on this match if (onlyMimeMatch == false && this.subMatchers != null && this.subMatchers.size() > 0) { for (int i = 0; i < this.subMatchers.size(); i++) { final MagicMatcher m = this.subMatchers.get(i); if ((submatch = m.test(f, false)) != null) { match1.addSubMatch(submatch); } } } } file.close(); return match1; }