/** string FXMLElement::getValueFromPath(string path); * * Added by cmicali * Purpose: get the value of the node referenced by the dot-path notation * example: * * <config> * <general> * <size>50</size> * <general> * </config> * * FXMLElement *n = fxml.ParseFile("abovefile.xml"); * // n is now a pointer to root node "config" * std::string s = n->getValueFromPath("general.size"); * // String s now is "50" */ std::string FXMLElement::getValueFromPath(std::string path) { int f = path.find(".",0); int o = 0; std::list<std::string> l; path = path + "."; while (f != std::string::npos) { std::string s = path.substr(o,f-o); if (s != "") l.push_back(s); o = f+1; f = path.find(".", o);; } std::list<std::string>::const_iterator iter; iter=l.begin(); if (iter != l.end()) { std::string s = (*iter); FXMLElement *n = findChild(this, s); iter++; if (!n) return ""; for (; iter != l.end(); iter++) { s = (*iter); n = findChild(n, s); if (!n) return ""; } return n->Value(); } return ""; }
FXMLElement* FXMLParser::ParseElement(std::string sCurInput, long* nLoc, long* nLineCount) { int nMode = PARSE_MODE_NONE; //set the initial mode std::string sWord(""); //set the current word read char ch; //current character read std::string sAttributeName; //attribute name to save int nSpecialMode; //if parsing comments, used to save old mode FXMLElement *fxInput = NULL; FXMLElement *fxChild = NULL; std::string sElementName; //element name, to be used for error checking //parse the line a char at a time for (long i = (*nLoc); i < sCurInput.length(); i++) { ch = sCurInput.at(i); if (ch == '<') { //parse the start of new elements if (nMode == PARSE_MODE_NONE) { //the beginning of an element nMode = PARSE_MODE_ELEMENT_PROVISIONAL; //create a new input element if (fxInput == NULL) { fxInput = new FXMLElement; fxInput->fxParent = NULL; } } else if ((nMode == PARSE_MODE_ELEMENT_DATA) || (nMode == PARSE_MODE_CDATA_END)) { nMode = PARSE_MODE_END_PROVISIONAL; //see if this is the last element or not if (sCurInput.at(i + 1) == '/') { //it is a last element, set mode fxInput->Value(sWord); nMode = PARSE_MODE_END; sWord.erase(); } else { //if not last element, perform recursive call if (fxInput->mChildren == NULL) fxInput->mChildren = new std::list<FXMLElement*>; fxChild = ParseElement(sCurInput, &i, nLineCount); if (fxChild != NULL) { fxChild->fxParent = fxInput; //V 0.92 Elements now in order thanks to //Max Belugin - [email protected] fxInput->mChildren->push_back(fxChild); } //set mode, initialize sWord with existing data nMode = PARSE_MODE_ELEMENT_DATA; //V0.93 removed - to be fixed later //sWord = fxInput->Value(); } } else if (nMode == PARSE_MODE_CDATA) { sWord.append(1, ch); } } else if ((ch == ' ') || (ch == '\n') || (ch == '\r') || (ch == '\t')) { //if in element data, add it. Else end state //also, do not add newlines or spaces to data if (nMode == PARSE_MODE_ELEMENT_DATA) { if (sWord.length() > 0) sWord.append(1,ch); } else if ((nMode == PARSE_MODE_CDATA) || (nMode == PARSE_MODE_ATTRIBUTE_VALUE)) //V 0.92 Attribute values with spaces now valid thanks to Max Belugin - [email protected] sWord.append(1, ch); else if (nMode == PARSE_MODE_ELEMENT_NAME) { //set the element name sElementName = sWord; fxInput->Name(sWord); sWord.erase(); //now set to look for attributes nMode = PARSE_MODE_ATTRIBUTE_PROVISIONAL; } //increment line count if \n if (ch == '\n') (*nLineCount)++; } else if ((ch == '?') || (ch == '!')) { //its a comment or declaration. For this version //of the parser, ignore them if (nMode == PARSE_MODE_ELEMENT_PROVISIONAL) { //save the old mode nSpecialMode = nMode; nMode = PARSE_MODE_SPECIAL; } } else if (ch == '[') { //look out for cdata tags if (nMode == PARSE_MODE_SPECIAL) { if (sCurInput.substr(i+1, 5).compare("CDATA") == 0) nMode = PARSE_MODE_CDATA_PROVISIONAL; } else if (nMode == PARSE_MODE_CDATA_PROVISIONAL) { sWord.erase(); nMode = PARSE_MODE_CDATA; } else sWord.append(1, ch); } else if (ch == ']') { //look for end of CDATA if (nMode == PARSE_MODE_CDATA) nMode = PARSE_MODE_CDATA_END_PROVISIONAL; else if (nMode == PARSE_MODE_CDATA_END_PROVISIONAL) nMode = PARSE_MODE_CDATA_END; else sWord.append(1, ch); } else if (ch == '>') { //end of element name if (nMode == PARSE_MODE_ELEMENT_NAME) { //set the element name sElementName = sWord; fxInput->Name(sWord); sWord.erase(); //now set more to look for element data nMode = PARSE_MODE_ELEMENT_DATA; } else if (nMode == PARSE_MODE_ATTRIBUTE_PROVISIONAL) { //attribute parsing over, prepare to parse element data sWord.erase(); nMode = PARSE_MODE_ELEMENT_DATA; } else if (nMode == PARSE_MODE_END) { //end of the element //only compare IF sWord.length > 0 if (sWord.length() > 0) { if (sWord.compare(sElementName) != 0) { //parse error!!! //V0.93 handle parse errors nicely! char* cError = (char*)malloc(6); sprintf(cError, "%d", (*nLineCount)); sError = (std::string)"FXML reports parsing error. Unmatched tag: Expecting " + sElementName + (std::string)" but encountered " + sWord + (std::string)" at line: " + cError; free(cError); delete fxInput; fxInput = NULL; } } //V0.93 //do NOT skip ahead one if xml file stuffed together //handles <xml>blah</xml><more>data</more> correctly //parse element data sWord.erase(); if (sCurInput.length() > (i + 1)) { if ((sCurInput.at(i + 1) =='\n') || (sCurInput.at(i + 1) =='\r')) { (*nLoc) = i + 1; } else (*nLoc) = i; } else (*nLoc) = i; return fxInput; } else if (nMode == PARSE_MODE_SPECIAL) { //end of a special element, reset the mode nMode = nSpecialMode; } else if (nMode == PARSE_MODE_CDATA) { sWord.append(1, ch); } } else if (ch == '/') { //handle elements such as <blah ..... /> if (nMode == PARSE_MODE_ATTRIBUTE_PROVISIONAL) { nMode = PARSE_MODE_END; } else if ((nMode != PARSE_MODE_SPECIAL) && (nMode != PARSE_MODE_END)) sWord.append(1, ch); } else if (ch == '=') { //parsing of attributes if (nMode == PARSE_MODE_ATTRIBUTE_NAME) { //set the attribute name sAttributeName = sWord; sWord.erase(); //set the mode nMode = PARSE_MODE_ATTRIBUTE_VALUE_PROVISIONAL; } else if (nMode != PARSE_MODE_SPECIAL) sWord.append(1, ch); } else if ((ch == '"') || (ch == '\'')) { //parsing of attributes if (nMode == PARSE_MODE_ATTRIBUTE_VALUE_PROVISIONAL) { nMode = PARSE_MODE_ATTRIBUTE_VALUE; } else if (nMode == PARSE_MODE_ATTRIBUTE_VALUE) { //save the pair fxInput->SetAttributePair(sAttributeName, sWord); //erase sWord.erase(); sAttributeName.erase(); //set new mode nMode = PARSE_MODE_ATTRIBUTE_PROVISIONAL; } else if (nMode != PARSE_MODE_SPECIAL) sWord.append(1, ch); } else { //parsing of straight text/words if (nMode == PARSE_MODE_ELEMENT_PROVISIONAL) nMode = PARSE_MODE_ELEMENT_NAME; else if (nMode == PARSE_MODE_ATTRIBUTE_PROVISIONAL) nMode = PARSE_MODE_ATTRIBUTE_NAME; //ignore comments and special declarations if ((nMode != PARSE_MODE_SPECIAL) && (nMode != PARSE_MODE_CDATA_END)) sWord.append(1, ch); } } return NULL; }
/////////////////////////////////////////////////////// // // Name: ReadAndWriteSocket // Params: sd - socket to read/write from // Returns: BOOLEAN success // Description: Reads XML query from socket, writes // XML result set /////////////////////////////////////////////////////// bool ReadAndWriteSocket(SOCKET sd) { // Read data from client char acReadBuffer[kBufferSize]; int nReadBytes = 0; //number of bytes read std::string sRead, sTemp, sResult; //string to read, and result int nFind; //result var BOOL bAllDone = FALSE;//whether the transaction is finished or not //variables for setting up timeout fd_set read_fds; struct timeval TimeOut; FD_ZERO(&read_fds); FD_SET(sd, &read_fds); TimeOut.tv_sec = gnThreadTimeout; //use timeout of durartion gnThreadTimeout TimeOut.tv_usec = 0; try { if (select(FD_SETSIZE, &read_fds, NULL, NULL, &TimeOut) != SOCKET_ERROR) { if (FD_ISSET(sd, &read_fds)) { do { nReadBytes = recv(sd, acReadBuffer, kBufferSize, 0); if (nReadBytes > 0) { LogEvent("ReadWriteSocket reports receiving client data", 1); //copy over inbound buffer sTemp = acReadBuffer; sRead.append(sTemp.substr(0,nReadBytes)); sTemp.erase(); //search for the end of XML. If found, we have received //all data. If not found, keep receiving data nFind = sRead.find("</request>"); if (nFind > 0) { //parse out request FXMLParser fxParse; //xml parser FXMLElement *fxElem = NULL; try { fxElem = fxParse.ParseString(sRead.c_str()); //parse string } catch(...) { LogEvent("ReadAndWriteSocket reports fXML Parser exception.", 2); break; } FXMLElement *fxRet = NULL; std::string sConnectionString, sSQL; //if string is not XML , exit if ((fxElem == NULL) || (fxParse.sError.length() > 0)) { LogEvent("ReadWriteSocket reports receiving invalid XML string", 2); break; } //get connection string fxRet = FindChildByName("connectionstring", fxElem, fxElem->mChildren->begin()); if (fxRet != NULL) sConnectionString = fxRet->Value(); else { LogEvent("ReadWriteSocket reports no connection string found.",2); break; } fxRet = NULL; //get SQL fxRet = FindChildByName("sql", fxElem, fxElem->mChildren->begin()); if (fxRet != NULL) sSQL = fxRet->Value(); else { LogEvent("ReadWriteSocket reports no SQL string found.",2); break; } if ((sConnectionString.length() == 0) || (sSQL.length() == 0)) break; //now sub in > for < , etc.. sSQL = SubStrReplace(sSQL, "<", "<" ); sSQL = SubStrReplace(sSQL, ">", ">"); sSQL = SubStrReplace(sSQL, "&", "&"); LogEvent(((std::string)"ReadWriteSocket reports executing SQL:" + sSQL).c_str(), 1); //now execute SQL sResult = ExecSQL(sConnectionString, sSQL); //now send back response nReadBytes = sResult.length(); int nSentBytes = 0; while (nSentBytes < nReadBytes) { nSentBytes = send(sd, sResult.c_str() + nSentBytes, nReadBytes - nSentBytes, 0); if (nSentBytes <= 0) { //closed connection or something LogEvent("ReadWriteSocket reports no data to return", 1); break; } }//while bAllDone = TRUE; sRead = ""; } //nfind > 0 //look for termination request }//nreadbytes > 0 } while ((nReadBytes > 0) && (!bAllDone)); }//FD_ISSET }//select else if (nReadBytes == SOCKET_ERROR) { LogEvent("ReadWriteSocket reports socket error after data return. Not necessarily a problem.", 1); } if (!bAllDone) LogEvent("ReadWriteSocket reports invalid data received, no SQL executed.", 2); } catch(...) { LogEvent("ReadAndWriteSocket reports fatal exception reading data.",2); } try { SOCKETMAP::iterator iSocket; //socket iterator if (ShutdownConnection(sd)) { LogEvent("ReadAndWriteSocket reports closing connection", 1); } else { LogEvent(WSAGetLastErrorMessage("shutdown connection"),2); } EnterCriticalSection(&gcsLock); try { iSocket = gmSockets.find(sd); gmSockets.erase(iSocket); } catch(...) { } LeaveCriticalSection(&gcsLock); } catch(...) { LogEvent("ReadAndWriteSocket reports fatal exception closing connection.",2); } return true; }