181 lines
4.9 KiB
C++
181 lines
4.9 KiB
C++
/*
|
|
Copyright (C) 2011 Srivats P.
|
|
|
|
This file is part of "Ostinato"
|
|
|
|
This is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
#include "textprotopdml.h"
|
|
|
|
#include "textproto.pb.h"
|
|
|
|
PdmlTextProtocol::PdmlTextProtocol()
|
|
{
|
|
ostProtoId_ = OstProto::Protocol::kTextProtocolFieldNumber;
|
|
}
|
|
|
|
PdmlProtocol* PdmlTextProtocol::createInstance()
|
|
{
|
|
return new PdmlTextProtocol();
|
|
}
|
|
|
|
void PdmlTextProtocol::preProtocolHandler(QString /*name*/,
|
|
const QXmlStreamAttributes &attributes, int expectedPos,
|
|
OstProto::Protocol *pbProto, OstProto::Stream *stream)
|
|
{
|
|
bool isOk;
|
|
int size;
|
|
int pos = attributes.value("pos").toString().toUInt(&isOk);
|
|
|
|
if (!isOk)
|
|
{
|
|
if (expectedPos >= 0)
|
|
expPos_ = pos = expectedPos;
|
|
else
|
|
goto _skip_pos_size_proc;
|
|
}
|
|
|
|
size = attributes.value("size").toString().toUInt(&isOk);
|
|
if (!isOk)
|
|
goto _skip_pos_size_proc;
|
|
|
|
// If pos+size goes beyond the frame length, this is a "reassembled"
|
|
// protocol and should be skipped
|
|
if ((pos + size) > int(stream->core().frame_len()))
|
|
goto _skip_pos_size_proc;
|
|
|
|
expPos_ = pos;
|
|
endPos_ = expPos_ + size;
|
|
|
|
_skip_pos_size_proc:
|
|
qDebug("expPos_ = %d, endPos_ = %d", expPos_, endPos_);
|
|
OstProto::TextProtocol *text = pbProto->MutableExtension(
|
|
OstProto::textProtocol);
|
|
|
|
text->set_port_num(0);
|
|
text->set_eol(OstProto::TextProtocol::kCrLf); // by default we assume CRLF
|
|
|
|
detectEol_ = true;
|
|
contentType_ = kUnknownContent;
|
|
}
|
|
|
|
void PdmlTextProtocol::unknownFieldHandler(QString name, int pos, int size,
|
|
const QXmlStreamAttributes &attributes, OstProto::Protocol *pbProto,
|
|
OstProto::Stream* /*stream*/)
|
|
{
|
|
if (name == "http.file_data") // ignore as it's dup of other fields
|
|
return;
|
|
|
|
_retry:
|
|
switch(contentType_)
|
|
{
|
|
case kUnknownContent:
|
|
if (name == "data")
|
|
contentType_ = kOtherContent;
|
|
else
|
|
contentType_ = kTextContent;
|
|
goto _retry;
|
|
break;
|
|
|
|
case kTextContent:
|
|
{
|
|
OstProto::TextProtocol *text = pbProto->MutableExtension(
|
|
OstProto::textProtocol);
|
|
|
|
if ((name == "data")
|
|
|| (attributes.value("show") == "HTTP chunked response"))
|
|
{
|
|
contentType_ = kOtherContent;
|
|
goto _retry;
|
|
}
|
|
|
|
QByteArray line = QByteArray::fromHex(
|
|
attributes.value("value").toString().toUtf8());
|
|
foreach(char c, line) {
|
|
if (!isprint(c) && !isspace(c)) {
|
|
contentType_ = kOtherContent;
|
|
goto _retry;
|
|
}
|
|
}
|
|
|
|
if (pos < expPos_)
|
|
break;
|
|
|
|
if ((pos + size) > endPos_)
|
|
break;
|
|
|
|
if (pos > expPos_)
|
|
{
|
|
int gap = pos - expPos_;
|
|
QByteArray filler(gap, '\n');
|
|
|
|
if (text->eol() == OstProto::TextProtocol::kCrLf)
|
|
{
|
|
if (gap & 0x01) // Odd
|
|
{
|
|
filler.resize(gap/2 + 1);
|
|
filler[0]=int(' ');
|
|
}
|
|
else // Even
|
|
filler.resize(gap/2);
|
|
}
|
|
|
|
text->mutable_text()->append(filler.constData(), filler.size());
|
|
expPos_ += gap;
|
|
}
|
|
|
|
if (detectEol_)
|
|
{
|
|
if (line.right(2) == "\r\n")
|
|
text->set_eol(OstProto::TextProtocol::kCrLf);
|
|
else if (line.right(1) == "\r")
|
|
text->set_eol(OstProto::TextProtocol::kCr);
|
|
else if (line.right(1) == "\n")
|
|
text->set_eol(OstProto::TextProtocol::kLf);
|
|
|
|
detectEol_ = false;
|
|
}
|
|
|
|
// Convert line endings to LF only - Qt reqmt that TextProto honours
|
|
line.replace("\r\n", "\n");
|
|
line.replace('\r', '\n');
|
|
|
|
text->mutable_text()->append(line.constData(), line.size());
|
|
expPos_ += size;
|
|
break;
|
|
}
|
|
case kOtherContent:
|
|
// Do nothing!
|
|
break;
|
|
default:
|
|
Q_ASSERT(false);
|
|
}
|
|
}
|
|
|
|
void PdmlTextProtocol::postProtocolHandler(OstProto::Protocol *pbProto,
|
|
OstProto::Stream *stream)
|
|
{
|
|
OstProto::TextProtocol *text = pbProto->MutableExtension(
|
|
OstProto::textProtocol);
|
|
|
|
// Empty Text Content - remove ourselves
|
|
if (text->text().length() == 0)
|
|
stream->mutable_protocol()->RemoveLast();
|
|
|
|
expPos_ = endPos_ = -1;
|
|
detectEol_ = true;
|
|
contentType_ = kUnknownContent;
|
|
}
|