/***************************** ********************************************** * The following java code is based off of the mxp library which * was written in c++ by Thomas Mecir and as such follows the * same license. * Copyright (C) 2010 by slothmud.org * * splork@slothmud.org * If you use this code, could you please add the following link * somewhere on your projects page * <a href="http://www.slothmud.org">Slothmud - a multiplayer free online rpg game</a> * * His library can be found at http://www.kmuddy.com/libmxp/ * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program 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 Library General Public License for more details. * ***************************************************************************/ package com.jmxp; import java.util.HashMap; public class EntityManager { /** empty string, to speed up some things a little bit */ private String empty_string; /** partial entity */ private String partent; /** are we in an entity? */ private boolean inEntity; private HashMap<String, String> entities = new HashMap<String, String>(); private String ENTITY_NAMES[] = { "Aacute", "aacute", "Acirc", "acirc", "acute", "AElig", "aelig", "Agrave", "agrave", "amp", "apos", "Aring", "aring", "Atilde", "atilde", "Auml", "auml", "brvbar", "Ccedil", "ccedil", "cedil", "cent", "copy", "curren", "deg", "divide", "Eacute", "eacute", "Ecirc", "ecirc", "Egrave", "egrave", "ETH", "eth", "Euml", "euml", "frac12", "frac14", "frac34", "gt", "Iacute", "iacute", "Icirc", "icirc", "iexcl", "Igrave", "igrave", "iquest", "Iuml", "iuml", "laquo", "lt", "macr", "micro", "middot", "nbsp", "not", "Ntilde", "ntilde", "Oacute", "oacute", "Ocirc", "ocirc", "Ograve", "ograve", "ordf", "ordm", "Oslash", "oslash", "Otilde", "otilde", "Ouml", "ouml", "para", "plusmn", "pound", "quot", "raquo", "reg", "sect", "shy", "sup1", "sup2", "sup3", "szlig", "THORN", "thorn", "times", "Uacute", "uacute", "Ucirc", "ucirc", "Ugrave", "ugrave", "uml", "Uuml", "uuml", "Yacute", "yacute", "yen", }; private int ENTITY_DEF[] = { 193, 225, 194, 226, 180, 198, 230, 192, 224, 38, 39, 197, 229, 195, 227, 196, 228, 166, 199, 231, 184, 162, 169, 164, 176, 247, 201, 233, 202, 234, 200, 232, 208, 240, 203, 235, 189, 188, 190, 62, 205, 237, 206, 238, 161, 204, 236, 191, 207, 239, 171, 60, 175, 181, 183, 160, 172, 209, 241, 211, 243, 212, 244, 210, 242, 170, 186, 216, 248, 213, 245, 214, 246, 182, 177, 163, 34, 187, 174, 167, 173, 185, 178, 179, 223, 222, 254, 215, 218, 250, 219, 251, 217, 249, 168, 220, 252, 221, 253, 165, }; private static final int NUM_MXP_ENTITIES = 100; public EntityManager(boolean noStdEntities) { reset(noStdEntities); } //~cEntityManager (); /** * add or update entity */ public void addEntity (String name, String value) { if (name.equals("")) return; //add or modify the entity entities.put(name, value); } /** * delete entity */ public void deleteEntity (String name) { entities.remove(name); } public String entity(String name) { String result = entities.get(name); if ( result == null ) { result = ""; } return result; } public boolean exists(String name) { return entities.containsKey(name); }; /** * expand entities in a string */ public String expandEntities(String s, boolean finished) { String s1 = ""; if (!partent.equals("")) //some unfinished entity is waiting... { inEntity = true; } for (int i = 0; i < s.length(); i++ ) { char ch = s.charAt(i); if (inEntity) { if (ch == ';') //end of entity { inEntity = false; if (partent.equals("")) //received &; { s1 += "&;"; } else if (partent.charAt(0) == '_') //invalid entity name - IGNORED { partent = ""; } else if (partent.charAt(0) == '#') //&#nnn; entity { //compute number int n = 0; //starting from second character for (int j = 1; j < partent.length(); j++) { int x = partent.charAt(j) - 48; if ((x < 0) || (x > 9)) //WRONG { n = 0; break; } n = n * 10 + x; if (n > 255) //number too big! { n = 0; break; } } //verify number, IGNORE entity if it's wrong if ((n >= 32) && (n <= 255)) { s1 += (char) n; } partent = ""; } else { //now we have correct entity name, let's expand it, if possible :) if (entities.containsKey(partent)) s1 += entities.get(partent); else //keep the same string if the entity doesn't exist... s1 += "&" + partent + ";"; partent = ""; } } else if (ch == '&') //unterminated entity, new entity may start here { s1 += "&" + partent; partent = ""; //isEntity remains set } else if ((partent.equals("") && correct1(ch)) || ((!partent.equals("")) && correctN(ch))) { partent += ch; } //this wasn't an entity after all else { inEntity = false; s1 += "&" + partent + ch; partent = ""; } } else { if (ch == '&') inEntity = true; else //copy without change s1 += ch; } } //string ends in an unterminated entity, but only if the string is finished if (inEntity && finished) { s1 += "&" + partent; partent = ""; inEntity = false; } //return the resulting string return s1; } public boolean needMoreText() { return !partent.equals(""); } void reset(boolean noStdEntities) { partent = ""; entities.clear(); inEntity = false; if (noStdEntities) { return; } //restore standard HTML entities for (int i = 0; i < NUM_MXP_ENTITIES; i++) { String s = ""; s += (char)ENTITY_DEF[i]; entities.put(ENTITY_NAMES[i], s); } } //can this be the first letter of an entity? private boolean correct1 (char l) { return (((l >= 'a') && (l <= 'z')) || ((l >= 'A') && (l <= 'Z')) || (l == '#')); } //can this be a letter of entity? private boolean correctN (char l) { return (((l >= 'a') && (l <= 'z')) || ((l >= 'A') && (l <= 'Z')) || (l == '_') || ((l >= '0') && (l <= '9'))); } }