예제 #1
0
void HTTPConnection::readHeaders() {
    while (_socket->canReadLine()) {
        QByteArray line = _socket->readLine();
        QByteArray trimmed = line.trimmed();
        if (trimmed.isEmpty()) {
            _socket->disconnect(this, SLOT(readHeaders()));

            QByteArray clength = requestHeader("Content-Length");
            if (clength.isEmpty()) {
                _parentManager->handleHTTPRequest(this, _requestUrl);

            } else {
                bool success = false;
                auto length = clength.toInt(&success);
                if (!success) {
                    qWarning() << "Invalid header." << _address << trimmed;
                    respond("400 Bad Request", "The header was malformed.");
                    return;
                }

                // Storing big requests in memory gets expensive, especially on servers
                // with limited memory. So we store big requests in a temporary file on disk
                // and map it to faster read/write access.
                static const int MAX_CONTENT_SIZE_IN_MEMORY = 10 * 1000 * 1000;
                if (length < MAX_CONTENT_SIZE_IN_MEMORY) {
                    _requestContent = MemoryStorage::make(length);
                } else {
                    _requestContent = FileStorage::make(length);
                }

                connect(_socket, SIGNAL(readyRead()), SLOT(readContent()));

                // read any content immediately available
                readContent();
            }
            return;
        }
        char first = line.at(0);
        if (first == ' ' || first == '\t') { // continuation
            _requestHeaders[_lastRequestHeader].append(trimmed);
            continue;
        }
        int idx = trimmed.indexOf(':');
        if (idx == -1) {
            qWarning() << "Invalid header." << _address << trimmed;
            respond("400 Bad Request", "The header was malformed.");
            return;
        }
        _lastRequestHeader = trimmed.left(idx).toLower();
        QByteArray& value = _requestHeaders[_lastRequestHeader];
        if (!value.isEmpty()) {
            value.append(", ");
        }
        value.append(trimmed.mid(idx + 1).trimmed());
    }
}
예제 #2
0
파일: robot_control.c 프로젝트: k3po/k3po.c
/*
** Converts final message received into a results structure
** depending on the current state (FINISHED or ERROR)
** Returns NULL on error, results structure on success
**
** Arguments:
** msg - the last message received before reaching FINISHED or ERROR state
 */
result * getResults(char * msg){
	result * res = malloc(sizeof(result));
	if(res == NULL){
		perror("malloc");
		return NULL;
	}

	char * content = readContent(msg);
	if(content == NULL){
		free(res);
		return NULL;
	}

	if(state == FINISHED){
		int len = strlen(content);
		char * half = strstr(content, "content-length:");
		if(half == NULL){
			perror("strstr");
			return NULL;
		}
		int remain = strlen(half);

		char * expected_script = malloc(sizeof(char) * (len - remain) + 1);
		if(expected_script == NULL){
			perror("malloc");
			return NULL;
		}
		memcpy(expected_script, content, len - remain);
		*(expected_script + len - remain) = '\0';

		char * actual_script = readContent(half);

		free(content);
		if(actual_script == NULL){
			actual_script = "";
		}
		res->actual_script = actual_script;
		res->expected_script = expected_script;
	}
	else if(state == ERROR){
		res->actual_script = content;
		res->expected_script = "";
	}
	else{
		fprintf(stderr, "Cannot get results from current state: Must be ERROR or FINISHED\n");
		return NULL;
	}
	return res;
}
예제 #3
0
void DocxReader::readData(QIODevice* device)
{
	m_in_block = m_cursor.document()->blockCount();
	m_current_style.block_format = m_cursor.blockFormat();

	// Open archive
	QtZipReader zip(device);

	// Read archive
	if (zip.isReadable()) {
		const QString files[] = { QString::fromLatin1("word/styles.xml"), QString::fromLatin1("word/document.xml") };
		for (int i = 0; i < 2; ++i) {
			QByteArray data = zip.fileData(files[i]);
			if (data.isEmpty()) {
				continue;
			}
			m_xml.addData(data);
			readContent();
			if (m_xml.hasError()) {
				m_error = m_xml.errorString();
				break;
			}
			m_xml.clear();
		}
	} else {
		m_error = tr("Unable to open archive.");
	}

	// Close archive
	zip.close();

	QCoreApplication::processEvents();
}
예제 #4
0
void putLeds() {
  String content = readContent();
  StaticJsonBuffer<BUFFER_LENGTH + 1> jsonBuffer;
  JsonObject &json = jsonBuffer.parseObject(content);
  if (json.success()) {
    if (json.containsKey("green")) {
      green = json["green"];
    }
    if (json.containsKey("green_duration") && json["green_duration"] > 0) {
      green_timeout = millis() + (int) json["green_duration"] * 1000;
      green_timeout = max(green_timeout, 1);
    }
    if (json.containsKey("red")) {
      red = json["red"];
    }
    if (json.containsKey("red_duration") && json["red_duration"] > 0) {
      red_timeout = millis() + (int) json["red_duration"] * 1000;
      red_timeout = max(red_timeout, 1);
    }
    if (json.containsKey("yellow")) {
      yellow = json["yellow"];
    }
    if (json.containsKey("yellow_duration") && json["yellow_duration"] > 0) {
      yellow_timeout = millis() + (int) json["yellow_duration"] * 1000;
      yellow_timeout = max(yellow_timeout, 1);
    }
    updateLeds();
    sendResponse(204);
  } else {
    sendResponse(400);
  }
}
예제 #5
0
Problem ProblemLoader::load() {
  content = readContent();

  loadCriteria();
  loadNodes();
  p.analyze();
  return p;
}
예제 #6
0
파일: rjio.c 프로젝트: XilongPei/TreeServer
int  RJBufCopy( RJFILE *dest, RJFILE *src )
// copy src's rec_buf to dest' rec_buf
{
    int  i;
    for( i=RJ_TYPE; i<=RJ_DATA; i++ )
       if ( !writeContent(dest,i,readContent(src,i) )) return 0;
    return 1;
}
예제 #7
0
bool PwDatabaseV3::readDatabase(const QByteArray& dbBytes) {
    QDataStream stream (dbBytes);
    stream.setByteOrder(QDataStream::LittleEndian);

    PwHeaderV3::ErrorCode headerErrCode = header.read(stream);
    if (headerErrCode != PwHeaderV3::SUCCESS) {
        LOG("%s: %d", PwHeaderV3::getErrorMessage(headerErrCode).toUtf8().constData(), headerErrCode);
        emit dbLoadError(PwHeaderV3::getErrorMessage(headerErrCode), headerErrCode);
        return false;
    }

    /* Calculate the encryption key */
    setPhaseProgressBounds(UNLOCK_PROGRESS_KEY_TRANSFORM);
    PwDatabase::ErrorCode dbErr = transformKey(header.getMasterSeed(), header.getTransformSeed(),
            header.getTransformRounds(), combinedKey, masterKey);
    if (dbErr != PwDatabase::SUCCESS) {
        LOG("Cannot decrypt database - transformKey: %d", dbErr);
        emit dbLoadError(tr("Cannot decrypt database", "A generic error message"), dbErr);
        return false;
    }


    /* Decrypt data */
    setPhaseProgressBounds(UNLOCK_PROGRESS_DECRYPTION);
    int dataSize = dbBytes.size() - header.HEADER_SIZE;
    // DB header not needed for decryption
    QByteArray dbBytesWithoutHeader = dbBytes.right(dataSize);
    QByteArray decryptedData(dataSize, 0);
    ErrorCode err = decryptData(dbBytesWithoutHeader, decryptedData);
    Util::safeClear(dbBytesWithoutHeader);
    if (err != SUCCESS) {
        if (err == DECRYPTED_PADDING_ERROR || err == DECRYPTED_CHECKSUM_MISMATCH) {
            LOG("Cannot decrypt database - decryptData: %d", err);
            emit invalidPasswordOrKey();
        } else {
            // err == CANNOT_DECRYPT_DB
            // err == CONTENT_HASHING_ERROR
            // err == something else
            LOG("Cannot decrypt database - decryptData: %d", err);
            emit dbLoadError(tr("Cannot decrypt database", "An error message"), err);
        }
        return false;
    }

    /* Reading and parsing data*/
    setPhaseProgressBounds(UNLOCK_PROGRESS_PARSE_DATA);
    QDataStream decryptedDataStream(decryptedData);
    decryptedDataStream.setByteOrder(QDataStream::LittleEndian);
    err = readContent(decryptedDataStream);
    Util::safeClear(decryptedData);
    if (err != SUCCESS) {
        emit dbLoadError(tr("Cannot parse database", "An error message. Parsing refers to the analysis/understanding of file content (do not confuse with reading it)."), err);
        return false;
    }

    return true;
}
예제 #8
0
/*!
    Opens a text \a document selected from the QDocumentSelector and displays the text editor.
*/
void NotesDemo::openDocument( const QContent &document )
{
    // Sets the current document to the one selected.
    currentDocument = document;

    // Read in the text from the document, if the read is successful display the text editor.
    if ( readContent( editor->document(), &currentDocument ) ) {
        layout->setCurrentWidget( editor );
    }
}
예제 #9
0
void HTTPConnection::readContent() {
    int size = _requestContent.size();
    if (_socket->bytesAvailable() < size) {
        return;
    }
    _socket->read(_requestContent.data(), size);
    _socket->disconnect(this, SLOT(readContent()));

    _parentManager->handleHTTPRequest(this, _requestUrl.path());
}
예제 #10
0
bool
HttpClient::perform()
{
    writeRequest();
    if (!_conn->fresh() && (_conn->stream().obtain().size == 0)) {
        _conn.reset(new HttpConnection(_conn->server()));
        writeRequest();
    }
    return (readStatus() && readHeaders() && readContent());
}
예제 #11
0
void SpiceInfo::readContentFile(const QString &path)
{
    QFile file(path);
    if(!file.open(QFile::ReadOnly | QFile::Text))
    {
        qDebug() << __FILE__ << __LINE__ << "cannot open file.";
    }

    readContent(&file);
}
예제 #12
0
void HTTPConnection::readContent() {
    auto size = std::min(_socket->bytesAvailable(), _requestContent->bytesLeftToWrite());

    _requestContent->write(_socket->read(size));

    if (_requestContent->bytesLeftToWrite() == 0) {
        _socket->disconnect(this, SLOT(readContent()));

        _parentManager->handleHTTPRequest(this, _requestUrl.path());
    }
}
예제 #13
0
void XmlNoteReader::read()
{
    if( !this->QXmlStreamReader::device())
    {
        qDebug("XmlNoteReader::read failed: input device NULL");
        return;
    }

    // skip everything until <note-content>
    while(!atEnd())
    {
        readNext();

        if(name() == "note-content")
        {
            if(!document_) // if no document_ set where note content can be written into
                skipCurrentElement();
            else
                readContent();
        }
        else if(name() == "id" || name() == "uuid") // only "id" is written
        {
            QString idStr = readElementText();
            uuid_ = parseUuid(idStr);
        }
        else if(name() == "title")
        {
            title_ = readElementText();
        }
        else if(name() == "last-change-date")
        {
            lastChange_ = QDateTime::fromString(readElementText(),Qt::ISODate);
        }
        else if(name() == "last-metadata-change")
        {
            lastMetadataChange_ = QDateTime::fromString(readElementText(),Qt::ISODate);
        }
        else if(name() == "create-date")
        {
            createDate_ = QDateTime::fromString(readElementText(),Qt::ISODate);
        }
        else if(name() == "tag")
        {
            tag_ = readElementText();
        }

        if (QXmlStreamReader::hasError())
        {
            qDebug("XmlNoteReader::read failed: Error reading xml content");
            return;
        }
    }
}
예제 #14
0
void HTTPConnection::readHeaders() {
    while (_socket->canReadLine()) {
        QByteArray line = _socket->readLine();
        QByteArray trimmed = line.trimmed();
        if (trimmed.isEmpty()) {
            _socket->disconnect(this, SLOT(readHeaders()));

            QByteArray clength = _requestHeaders.value("Content-Length");
            if (clength.isEmpty()) {
                _parentManager->handleHTTPRequest(this, _requestUrl);

            } else {
                _requestContent.resize(clength.toInt());
                connect(_socket, SIGNAL(readyRead()), SLOT(readContent()));

                // read any content immediately available
                readContent();
            }
            return;
        }
        char first = line.at(0);
        if (first == ' ' || first == '\t') { // continuation
            _requestHeaders[_lastRequestHeader].append(trimmed);
            continue;
        }
        int idx = trimmed.indexOf(':');
        if (idx == -1) {
            qWarning() << "Invalid header." << _address << trimmed;
            respond("400 Bad Request", "The header was malformed.");
            return;
        }
        _lastRequestHeader = trimmed.left(idx);
        QByteArray& value = _requestHeaders[_lastRequestHeader];
        if (!value.isEmpty()) {
            value.append(", ");
        }
        value.append(trimmed.mid(idx + 1).trimmed());
    }
}
예제 #15
0
bool
HttpClient::readContent()
{
    if (_header.contentLengthGiven) {
        return readContent(_header.contentLength);
    } else if (_header.chunkedEncodingGiven) {
        size_t chunkSize = 0;
        for (bool first = true; readChunkSize(first, chunkSize); first = false) {
            if (chunkSize == 0) {
                return skipTrailers();
            }
            if (!readContent(chunkSize)) {
                return false;
            }
        }
        _handler.handleFailure("error reading HTTP chunk size");
        return false;
    } else { // data terminated by eof
        if (serverKeepAlive()) {
            _handler.handleFailure("server indicated keep-alive, "
                                   "but we need eof to terminate data");
            return false;
        }
        Input &input = _conn->stream();
        for (;;) {
            Memory mem = input.obtain();
            if (mem.size == 0) {
                if (_conn->stream().tainted()) {
                    _handler.handleFailure(strfmt("read error: '%s'",
                                                  _conn->stream().tainted().reason().c_str()));
                }
                return true;
            }
            _handler.handleContent(mem);
            input.evict(mem.size);
        }
    }
}
예제 #16
0
파일: main.c 프로젝트: zzjin13/OS_LAB
void readFileByPath(FILE* file, char* name, char* originPath, char* path, int offset, RootDir* rd, BOOL* found){

	int RD_Size = sizeof(RootDir);

	long point = ftell(file);
	fseek(file, offset, SEEK_SET);
	//printf("INpath:\n");
	//puts(path);
	//printf("\n");
	if(belongTo(path,originPath)){
		//printf("belongTo\n");
		do {
			memset(rd, 0, RD_Size);
			fread(rd, RD_Size, 1, file);
			if (isDir(rd)){
					int fst_Clus = rd->DIR_FstClus[0] + rd->DIR_FstClus[1] * 0x10;
					char* newPath = (char*)malloc(MAX);
					memset(newPath, 0, strlen(newPath));
					memcpy(newPath, path, strlen(path));
					RootDir oldRd;
					memcpy(&oldRd, rd, RD_Size);
					addToPath(newPath, rd->DIR_Name);
					readFileByPath(file,name,originPath, newPath, (fst_Clus * 0x200 + DATA_START), rd,found);
					memcpy(rd, &oldRd, RD_Size);
					free(newPath);
			}else{
				if (pathEquals(path,originPath)&&fileEquals(rd->DIR_Name,name)&&isValid(rd)){
					// printf("%s%s\n",path, rd->DIR_Name);
					int fatVal=rd->DIR_FstClus[0] + rd->DIR_FstClus[1] * 0x10;
					while(fatVal<0xFF8){
						readContent(file,fatVal);
						*found=TRUE;
						fatVal=getFATValue(file,fatVal);
						//printf("FATVAL:%3X\n",fatVal);
						if(fatVal==0xFF7){
							my_print("坏",1);
							my_print("簇",1);
							break;
						}
					}

					my_print("\n",1);
					return;
				}
			}
		}while(!isEmpty(rd));
	}
	fseek(file, point, SEEK_SET);

}
예제 #17
0
bool indri::parse::WARCRecord::readRecord() {
  metadata.clear();
  contentLength = 0;
  header = "";
  warcType = "";
  uuid = "";
  targetURI  = "";
  trecID = "";
  bool res = readHeader();
  if (! res) {
    return false;
  }  
  res = readContent();
  return res;
}
예제 #18
0
파일: G3D.cpp 프로젝트: SCIInstitute/SCIRun
void G3D::readSoA(AbstractReader& reader, G3D::GeometrySoA& geometry) {
    if (reader.isOpen()) {
        geometry.info = readHeader(reader);
        if (geometry.info.numberVertices == 0)
            return;
        if (geometry.info.vertexType == SoA)
            readContent(reader, geometry);
        else if (geometry.info.vertexType == AoS) {
            geometry.info.vertexType = SoA;
            geometry.indices = readIndices(reader, geometry.info);
            std::vector<float> vertices = readVertices(reader, geometry.info);
            geometry.vertexAttributes = convertVertices(vertices, geometry.info);
        }
    }
}
예제 #19
0
파일: rjio.c 프로젝트: XilongPei/TreeServer
short RJDateEnd(RJFILE *rf, char *date)
{
    char  	*s;
    char  	buf[256];
    SYSTEMTIME SystemTime;

    s = readContent(rf, RJ_TIME);
    strcpy(buf, s);
    getReallyClock(buf, &SystemTime);
    sprintf(buf, "%4d%02d%02d", SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay);

    if( strcmp(buf, date) > 0 )		return  1;
    return  0;

} // end of RJDateEnd()
예제 #20
0
파일: G3D.cpp 프로젝트: SCIInstitute/SCIRun
void G3D::readAoS(AbstractReader& reader, G3D::GeometryAoS& geometry) {
    if (reader.isOpen()) {
        geometry.info = readHeader(reader);
        if (geometry.info.numberVertices == 0)
            return;
        if (geometry.info.vertexType == AoS)
            readContent(reader, geometry);
        else if (geometry.info.vertexType == SoA) {
            geometry.info.vertexType = AoS;
            geometry.indices = readIndices(reader, geometry.info);
            auto vertexAttributes = readVertexAttributes(reader, geometry.info);
            geometry.vertices = convertVertices(vertexAttributes, geometry.info);
        }
    }
}
예제 #21
0
파일: webgetter.cpp 프로젝트: sasq64/apone
void HttpSession::sendRequest(const string &path, const string &host) {
	string req = utils::format("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", urlencode(path, "&#()!*[]:;\\;+'\" "), host);
	LOGD("REQ %p:\n%s", this, req);
	LOGD("%d", impl->data.size());
	impl->c.write(req);
	impl->state = CONNECT;
	asio::async_read_until(impl->c.getSocket(), impl->data, "\r\n\r\n", [=](const asio::error_code &e, size_t n) {
		//LOGD("Read %d bytes", n);
		parseHeader();
		impl->state = HEADERS;
		//if(impl->code == 200)
		readContent();
		//else
		//	impl->state = ERROR;
	});
}
예제 #22
0
void ChatWindow::on_sendButton_clicked()
{
    QString content = this->sendEdit->toPlainText();
    if(content != "")
    {
        QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        p2pMessage pm(this->username, this->friendName, time, content);
        Helper *helper = Helper::getInstance();
        helper->writeClient(pm);
        this->sendEdit->clear();
        this->messageEdit->append(QString("<span style=\"color: blue;\">") + this->username +  "</span> <span style=\"color:cyan;\">" + time + "</span>");
        readContent(content);
        Database *db = Database::getInstance(this->username);
        db->addMessage(this->friendName, 1, time, content);
    }
}
예제 #23
0
void putSettings() {
  String content = readContent();
  StaticJsonBuffer<BUFFER_LENGTH + 1> jsonBuffer;
  JsonObject &json = jsonBuffer.parseObject(content);
  if (json.success()) {
    if (json.containsKey("threshold")) {
      threshold = max(0, min(255, json["threshold"]));
      EEPROM.writeBlock(EEPROM_THRESHOLD_ADDR, &threshold, sizeof(threshold));
    }
    if (json.containsKey("hysteresis")) {
      hysteresis = max(0, min(255, json["hysteresis"]));
      EEPROM.writeBlock(EEPROM_HYSTERESIS_ADDR, &hysteresis, sizeof(hysteresis));
    }
    sendResponse(204);
  } else {
    sendResponse(400);
  }
}
예제 #24
0
bool Parser::readInt(int &nDato, const char cStopChar)
{
	std::string strTemp("");
	
	// Leemos el contenido en una cadena.
	readContent(strTemp, cStopChar);
	
	// Comprobamos que la cadena contenga un numero válido para pasarselo
	// a atoi() con total seguridad.	
	if(validInt(strTemp)) {
		nDato = atoi(strTemp.c_str());
		return true;
	}
	else {
		m_nError = 3; 
		return false;
	}
}
예제 #25
0
int extractHeaderData(FInfo *_file)
{
	char *OffsetBuff;
	int buffSize = 256 * 1024 * 1024;			//256MB
	OffsetBuff = (char*)malloc(sizeof(char) * buffSize);
	
	string xmlTileStr = "<?xml version='1.0' encoding='utf-8'?><EXLINKS>";
	string xmlEndTag = "</EXLINKS>\0";
		
	XMLParser(_file, OffsetBuff);
	rewind(_file->Header);
	
	fwrite(xmlTileStr.c_str(), 1, xmlTileStr.length(), _file->ExLinks);	
	readContent(_file, OffsetBuff);
	fputs(xmlEndTag.c_str(), _file->ExLinks);
	
	free(OffsetBuff);
	return 1;
}
예제 #26
0
bool Parser::readBloqueTxt(const std::string &strEtiqueta, std::string &strResultado)
{
    std::string strBufferEtq,
				strBufferCnt,
				strCierre("/");

	// Ignoramos hasta llegar a la apertura de una etiqueta.
    if(!ignorarChars())
        return false;
    
    // Leemos que etiqueta es.
    if(!readToken(strBufferEtq))
        return false;
    
    // Si no es la etiqueta que buscamos, devolvemos error.
    if(strEtiqueta != strBufferEtq)
        return false;
    
    // Leemos el contenido.
    if(!readContent(strBufferCnt, '<'))
        return false;
    
    // Antes de leer el cierre de la etiqueta, componemos la cadena para
    // comparar con dicho cierre. El cierre de la etiqueta debe ser igual 
    // que la apertura pero con una barra delante: 
    //	- Si apertura es <etiqueta>, el cierre debe ser </etiqueta>
    strCierre += strBufferEtq;
    strBufferEtq.clear();
    
    // Leemos el cierre de la etiqueta. 
    if(!readToken(strBufferEtq))
        return false;
    
    // Y comprobamos que sea el cierre correcto.
    if(strCierre != strBufferEtq)
        return false;

	// Copiamos el resultado para devolverlo.
    strResultado = strBufferCnt;
    return true;
}
예제 #27
0
파일: G3D.cpp 프로젝트: BlueBrain/TuvokIO
void G3D::read(const std::string & file, GeometrySoA * const geometry)
{
	std::fstream fs;
	fs.open(file.c_str(), std::fstream::in | std::fstream::binary);

	if (fs.is_open())
	{
		readHeader(fs, geometry->info);
		if (geometry->info.vertexType == SoA) readContent(fs, *geometry);
		else if (geometry->info.vertexType == AoS)
		{
			geometry->info.vertexType = SoA;
			readIndices(fs, geometry->indices, geometry->info);
			float * vertices = NULL;
			readVertices(fs, vertices, geometry->info);
			convertVertices(vertices, geometry->vertexAttributes, geometry->info);
			cleanVertices(vertices);
		}
		fs.close();
	}
}
예제 #28
0
IsoMediaFile::Configuration WriterConfig::readJson(const std::string& filename)
{
    Json::Reader jsonReader;
    std::ifstream configFile(filename);
    if (!configFile.is_open())
    {
        throw std::runtime_error("Unable to open input file '" + filename + "'");
    }

    // Parse the configuration file
    Json::Value jsonValues;
    const bool parsingSuccess = jsonReader.parse(configFile, jsonValues, false);
    if (not parsingSuccess)
    {
        throw std::runtime_error("Failed to parse input configuration: " + jsonReader.getFormatedErrorMessages());
    }

    // Read JSON values into local structures
    IsoMediaFile::Configuration configuration;
    configuration.general = readGeneral(jsonValues["general"]);

    // The Contents
    Json::Value contents = jsonValues["content"];
    if (contents.isNull())
    {
        throw std::runtime_error("No content section in input configuration.");
    }
    for (const auto& content : contents)
    {
        configuration.content.push_back(readContent(content));
    }

    configuration.egroups = readEgroups(jsonValues["egroups"]);

    confDump(configuration, jsonValues);
    return configuration;
}
예제 #29
0
bool Parser::processMeshFile(Shape *pShape, std::vector<MeshTriangle *> *MTList)
{	
	std::string 	strEtiqueta, strFile, strLine, strType;
	std::ifstream 	fsFile;
	
	Point			v;	// Vertice
	Vec3			n;	// Normal
	Vec2			t;	// Textura
	
	Mesh			*pMesh = dynamic_cast<Mesh *> (pShape);
		
	int				nVertex, nNormals, nTextures, nFaces;
	
	// Para el log
	nVertex = nNormals = nTextures = nFaces = 0;
	
	if(!readContent(strFile, '<'))
        return false;
        
	if(!readToken(strEtiqueta))
		return false;
		
	if(strEtiqueta != "/file")
		return false;
		
	// Abrir fichero
	fsFile.open(strFile.c_str());
	
	// Leemos el fichero linea a linea
	while(std::getline(fsFile, strLine)){
		if((strLine[0] == 'v') && (strLine[1] == ' ')) { // Vertice
			// Procesar vertice
						
			int i = 1; // Posicion en la linea
			
			// Evitamos los espacios antes del primer numero, si los hay
			while(strLine[i] == ' ') i++; 
			
			for(int j = 0; j < 3; j++) { // Tres veces para tres float
				std::string strTemp("");
						
				while(1) { // Hasta que no encontremos un espacio
					if((strLine[i] != ' ') && (i < (strLine.length() -1))) {
						strTemp = strTemp + strLine[i];
						i++; // Siguiente caracter
					}
					else
					{
						i++; 	// Saltamos el espacio en blanco
						break;
					}
				}
				
				if(strTemp.length() > 0) {
					if(validFloat(strTemp))
						v.e[j] = atof(strTemp.c_str());
					else {
						// Lanzar error
					}
				}
			}
			
			pMesh->addVertex(v);
            nVertex++;
		}
		else if((strLine[0] == 'v') && (strLine[1] == 'n')) { // Normal
			// Procesar normal
							
			int i = 3; // Posicion en la linea
			for(int j = 0; j < 3; j++) { // Tres veces para tres float
				std::string strTemp("");
				
				while(1) { // Hasta que no encontremos un espacio
					if((strLine[i] != ' ') && (i < (strLine.length() -1))) {
						strTemp = strTemp + strLine[i];
						i++; // Siguiente caracter
					}
					else
					{
						i++; 	// Saltamos el espacio en blanco
						break;
					}
				}
				
				if(strTemp.length() > 0) {
					if(validFloat(strTemp))
						n.e[j] = atof(strTemp.c_str());
					else {
						// Lanzar error
					}
				}
			}
			
			pMesh->addNormal(n);
            nNormals++;
		}
		else if((strLine[0] == 'v') && (strLine[1] == 't')) { // Texture
			// Procesar textura
			
			int i = 3; // Posicion en la linea
			for(int j = 0; j < 2; j++) { // Dos veces para Dos float
				std::string strTemp("");
				
				while(1) { // Hasta que no encontremos un espacio
					if((strLine[i] != ' ') && (i < (strLine.length() -1))) {
						strTemp = strTemp + strLine[i];
						i++; // Siguiente caracter
					}
					else
					{
						i++; 	// Saltamos el espacio en blanco
						break;
					}
				}
				
				if(strTemp.length() > 0) {
					if(validFloat(strTemp))
						t.e[j] = atof(strTemp.c_str());
					else {
						// Lanzar error
					}
				}
			}			
			
            pMesh->addTexture(t);
            nTextures++;
		}
		else if((strLine[0] == 'f') && (strLine[1] == ' ')) { // Face
			// Procesar face		
			
			MeshFace mfFace(-1);			
			
			int i = 2, nBlock = 0;
			while(nBlock < 3) {
				int nNumber = 0; 			// Primer numero del bloque
				std::string strTemp(""); 	// Temporal para almacenar numeros
				
				while(nNumber < 3) { // Repetir hasta el tercer numero
					if(strLine[i] == '/') { // Fin de numero, excepto el ultimo del bloque
						// Si la cadena temporal tiene un entero valido
						if((strTemp.length() > 0) && validInt(strTemp)) { 
							switch(nNumber) { // Veamos que posicion tenemos
								case 0: // Vertice
									mfFace.nVIndex[nBlock] = atoi(strTemp.c_str()) - 1;									
									break;
								case 1: // Textura
									mfFace.nTIndex[nBlock] = atoi(strTemp.c_str()) - 1;
									break;
							}
						}
						// Si la cadena está vacía o el numero no es valido
						// no almacenamos nada. El valor está por defecto a -1,
						// con lo que el render sabrá qué hacer en caso de
						// encontrarlo.						
						
						strTemp.clear(); 	// Limpiamos la cadena
						nNumber++;			// Siguiente numero		
						i++;				// Avanzamos en la linea
					}
					else if(strLine[i] == ' ') { // Fin de bloque
						// Almacenamos el numero, si lo hay
						if((strTemp.length() > 0) && validInt(strTemp)) {
							switch(nNumber) {
								case 0: // Vertice
									mfFace.nVIndex[nBlock] = atoi(strTemp.c_str()) - 1;									
									break;
								case 1: // Textura
									mfFace.nTIndex[nBlock] = atoi(strTemp.c_str()) - 1;
									break;
								case 2: // Normal
									mfFace.nNIndex[nBlock] = atoi(strTemp.c_str()) - 1;
									break;
							}
						}
									
						nNumber = 3;	// Salimos del while
						nBlock++;		// Nuevo bloque
						i++;			// Avanzamos por la cadena
					}
					else if(i == (strLine.length() - 1)) { // Final de linea
						// Almacenamos el numero, si lo hay
						if((strTemp.length() > 0) && validInt(strTemp)) {
							switch(nNumber) {
								case 0: // Vertice
									mfFace.nVIndex[nBlock] = atoi(strTemp.c_str()) - 1;									
									break;
								case 1: // Textura
									mfFace.nTIndex[nBlock] = atoi(strTemp.c_str()) - 1;
									break;
								case 2: // Normal
									mfFace.nNIndex[nBlock] = atoi(strTemp.c_str()) - 1;
									break;
							}
						}
						
						nNumber = 3;
						nBlock = 3; 	// Salimos de ambos while
					}
					else { // Metemos el caracter en la cadena temporal, y seguimos
						strTemp = strTemp + strLine[i];
						i++;
					}
				}
			}
			
			// Creamos el nuevo triangulo.
			MeshTriangle *pNewT = new MeshTriangle(mfFace, pMesh);
			// Lo añadimos a la lista
			MTList->push_back(pNewT);
			
			// Incrementamos el numero de triangulos en la malla
			pMesh->increaseTriangleCount();
			
			nFaces++;		
		}
	}
	fsFile.close();
	
	return true;
}