File indexing completed on 2024-04-28 15:35:14
0001 /*************************************************************************** 0002 * Copyright (C) 2004 by Tomas Mecir * 0003 * kmuddy@kmuddy.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Library General Public License as * 0007 * published by the Free Software Foundation; either version 2 of the * 0008 * License, or (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU Library General Public License for more details. * 0014 ***************************************************************************/ 0015 0016 #include "centitymanager.h" 0017 0018 #include "entitylist.h" 0019 0020 cEntityManager::cEntityManager (bool noStdEntities) 0021 { 0022 reset (noStdEntities); 0023 } 0024 0025 cEntityManager::~cEntityManager () 0026 { 0027 entities.clear (); 0028 } 0029 0030 void cEntityManager::reset (bool noStdEntities) 0031 { 0032 partent = ""; 0033 entities.clear (); 0034 inEntity = false; 0035 0036 if (noStdEntities) 0037 return; 0038 0039 char s[2]; 0040 s[1] = 0; 0041 //restore standard HTML entities 0042 for (int i = 0; i < NUM_MXP_ENTITIES; i++) 0043 { 0044 s[0] = ENTITY_DEF[i]; 0045 entities[ENTITY_NAMES[i]] = s; 0046 } 0047 } 0048 0049 //can this be the first letter of an entity? 0050 inline bool correct1 (char l) 0051 { 0052 return (((l >= 'a') && (l <= 'z')) || ((l >= 'A') && (l <= 'Z')) || (l == '#')); 0053 } 0054 0055 //can this be a letter of entity? 0056 inline bool correctN (char l) 0057 { 0058 return (((l >= 'a') && (l <= 'z')) || ((l >= 'A') && (l <= 'Z')) || (l == '_') || 0059 ((l >= '0') && (l <= '9'))); 0060 } 0061 0062 void cEntityManager::addEntity (const string &name, const string &value) 0063 { 0064 if (name.empty()) return; 0065 0066 //add or modify the entity 0067 entities[name] = value; 0068 } 0069 0070 void cEntityManager::deleteEntity (const string &name) 0071 { 0072 entities.erase (name); 0073 } 0074 0075 string cEntityManager::entity (const string &name) 0076 { 0077 if (exists (name)) 0078 return entities[name]; 0079 //return empty string otherwise 0080 return empty_string; 0081 } 0082 0083 string cEntityManager::expandEntities (const string &s, bool finished) 0084 { 0085 string s1; 0086 0087 if (!partent.empty ()) //some unfinished entity is waiting... 0088 inEntity = true; 0089 0090 string::const_iterator it; 0091 for (it = s.begin(); it != s.end(); ++it) 0092 if (inEntity) 0093 { 0094 char ch = *it; 0095 if (ch == ';') //end of entity 0096 { 0097 inEntity = false; 0098 if (partent.empty()) //received &; 0099 { 0100 s1 += "&;"; 0101 } 0102 else 0103 if (partent[0] == '_') //invalid entity name - IGNORED 0104 { 0105 partent = ""; 0106 } 0107 else 0108 if (partent[0] == '#') //&#nnn; entity 0109 { 0110 //compute number 0111 int n = 0; 0112 string::iterator it2 = partent.begin(); 0113 it2++; //starting from second character 0114 for (; it2 != partent.end(); ++it2) 0115 { 0116 int x = *it2 - 48; 0117 if ((x < 0) || (x > 9)) //WRONG 0118 { 0119 n = 0; 0120 break; 0121 } 0122 n = n * 10 + x; 0123 if (n > 255) //number too big! 0124 { 0125 n = 0; 0126 break; 0127 } 0128 } 0129 //verify number, IGNORE entity if it's wrong 0130 if ((n >= 32) && (n <= 255)) 0131 s1 += (unsigned char) n; 0132 partent = ""; 0133 } 0134 else 0135 { 0136 //now we have correct entity name, let's expand it, if possible :) 0137 if (entities.count (partent)) 0138 s1 += entities[partent]; 0139 else 0140 //keep the same string if the entity doesn't exist... 0141 s1 += "&" + partent + ";"; 0142 partent = ""; 0143 } 0144 } 0145 else if (ch == '&') 0146 //unterminated entity, new entity may start here 0147 { 0148 s1 += "&" + partent; 0149 partent = ""; 0150 //isEntity remains set 0151 } 0152 else if ((partent.empty() && correct1(ch)) || ((!partent.empty()) && correctN(ch))) 0153 { 0154 partent += ch; 0155 } 0156 //this wasn't an entity after all 0157 else 0158 { 0159 inEntity = false; 0160 s1 += "&" + partent + ch; 0161 partent = ""; 0162 } 0163 } 0164 else 0165 { 0166 if (*it == '&') 0167 inEntity = true; 0168 else 0169 //copy without change 0170 s1 += *it; 0171 } 0172 //string ends in an unterminated entity, but only if the string is finished 0173 if (inEntity && finished) 0174 { 0175 s1 += "&" + partent; 0176 partent = ""; 0177 inEntity = false; 0178 } 0179 0180 //return the resulting string 0181 return s1; 0182 } 0183 0184 bool cEntityManager::needMoreText() 0185 { 0186 return partent.empty() ? false : true; 0187 }