1bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber/* 2bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Copyright 2012, The Android Open Source Project 3bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * 4bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * you may not use this file except in compliance with the License. 6bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * You may obtain a copy of the License at 7bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * 8bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * 10bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Unless required by applicable law or agreed to in writing, software 11bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * See the License for the specific language governing permissions and 14bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * limitations under the License. 15bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber */ 16bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 17bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include "ParsedMessage.h" 18bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 19bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <ctype.h> 20bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 21bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/ADebug.h> 228060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber#include <media/stagefright/foundation/hexdump.h> 23bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 24bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubernamespace android { 25bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 26bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static 27bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubersp<ParsedMessage> ParsedMessage::Parse( 28bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber const char *data, size_t size, bool noMoreData, size_t *length) { 29bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber sp<ParsedMessage> msg = new ParsedMessage; 30bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ssize_t res = msg->parse(data, size, noMoreData); 31bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 32bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (res < 0) { 33bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *length = 0; 34bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return NULL; 35bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 36bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 37bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *length = res; 38bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return msg; 39bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 40bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 41bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberParsedMessage::ParsedMessage() { 42bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 43bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 44bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberParsedMessage::~ParsedMessage() { 45bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 46bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 47bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::findString(const char *name, AString *value) const { 48bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString key = name; 49bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber key.tolower(); 50bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 51bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ssize_t index = mDict.indexOfKey(key); 52bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 53bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (index < 0) { 54bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber value->clear(); 55bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 56bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 57bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 58bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 59bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *value = mDict.valueAt(index); 60bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return true; 61bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 62bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 63bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::findInt32(const char *name, int32_t *value) const { 64bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString stringValue; 65bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 66bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (!findString(name, &stringValue)) { 67bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 68bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 69bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 70bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber char *end; 71bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *value = strtol(stringValue.c_str(), &end, 10); 72bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 73bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (end == stringValue.c_str() || *end != '\0') { 74bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *value = 0; 75bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 76bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 77bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 78bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return true; 79bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 80bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 81bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberconst char *ParsedMessage::getContent() const { 82bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return mContent.c_str(); 83bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 84bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 85bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberssize_t ParsedMessage::parse(const char *data, size_t size, bool noMoreData) { 86bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (size == 0) { 87bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return -1; 88bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 89bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 90bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ssize_t lastDictIndex = -1; 91bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 92bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t offset = 0; 938060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber bool headersComplete = false; 94bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber while (offset < size) { 95bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t lineEndOffset = offset; 96bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber while (lineEndOffset + 1 < size 97bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber && (data[lineEndOffset] != '\r' 98bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber || data[lineEndOffset + 1] != '\n')) { 99bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ++lineEndOffset; 100bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 101bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 102bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (lineEndOffset + 1 >= size) { 103bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return -1; 104bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 105bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 106bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString line(&data[offset], lineEndOffset - offset); 107bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 108bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (offset == 0) { 109bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber // Special handling for the request/status line. 110bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 111bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber mDict.add(AString("_"), line); 112bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber offset = lineEndOffset + 2; 113bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 114bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber continue; 115bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 116bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 117bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (lineEndOffset == offset) { 1188060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber // An empty line separates headers from body. 1198060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber headersComplete = true; 120bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber offset += 2; 121bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber break; 122bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 123bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 124bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') { 125bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber // Support for folded header values. 126bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 127bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (lastDictIndex >= 0) { 128bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber // Otherwise it's malformed since the first header line 129bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber // cannot continue anything... 130bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 131bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString &value = mDict.editValueAt(lastDictIndex); 132bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber value.append(line); 133bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 134bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 135bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber offset = lineEndOffset + 2; 136bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber continue; 137bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 138bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 139bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ssize_t colonPos = line.find(":"); 140bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (colonPos >= 0) { 141bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString key(line, 0, colonPos); 142bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber key.trim(); 143bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber key.tolower(); 144bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 145bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.erase(0, colonPos + 1); 146bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 147bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber lastDictIndex = mDict.add(key, line); 148bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 149bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 150bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber offset = lineEndOffset + 2; 151bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 152bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 1538060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber if (!headersComplete && (!noMoreData || offset == 0)) { 1548060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber // We either saw the empty line separating headers from body 1558060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber // or we saw at least the status line and know that no more data 1568060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber // is going to follow. 1578060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber return -1; 1588060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber } 1598060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber 160bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber for (size_t i = 0; i < mDict.size(); ++i) { 161bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber mDict.editValueAt(i).trim(); 162bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 163bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 164bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber int32_t contentLength; 165bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (!findInt32("content-length", &contentLength) || contentLength < 0) { 166bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber contentLength = 0; 167bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 168bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 169bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t totalLength = offset + contentLength; 170bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 171bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (size < totalLength) { 172bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return -1; 173bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 174bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 175bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber mContent.setTo(&data[offset], contentLength); 176bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 177bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return totalLength; 178bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 179bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 1808060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huberbool ParsedMessage::getRequestField(size_t index, AString *field) const { 181bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString line; 182bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber CHECK(findString("_", &line)); 183bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 184bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t prevOffset = 0; 185bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t offset = 0; 186bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber for (size_t i = 0; i <= index; ++i) { 1878060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber if (offset >= line.size()) { 1888060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber return false; 1898060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber } 1908060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber 191bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ssize_t spacePos = line.find(" ", offset); 192bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 193bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (spacePos < 0) { 194bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber spacePos = line.size(); 195bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 196bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 197bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber prevOffset = offset; 198bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber offset = spacePos + 1; 199bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 200bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 201bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber field->setTo(line, prevOffset, offset - prevOffset - 1); 2028060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber 2038060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber return true; 204bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 205bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 206bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::getStatusCode(int32_t *statusCode) const { 207bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString statusCodeString; 2088060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber if (!getRequestField(1, &statusCodeString)) { 2098060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber *statusCode = 0; 2108060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber return false; 2118060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber } 212bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 213bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber char *end; 214bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *statusCode = strtol(statusCodeString.c_str(), &end, 10); 215bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 216bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (*end != '\0' || end == statusCodeString.c_str() 217bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber || (*statusCode) < 100 || (*statusCode) > 999) { 218bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *statusCode = 0; 219bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 220bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 221bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 222bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return true; 223bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 224bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 225bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberAString ParsedMessage::debugString() const { 226bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString line; 227bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber CHECK(findString("_", &line)); 228bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 229bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append("\n"); 230bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 231bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber for (size_t i = 0; i < mDict.size(); ++i) { 232bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber const AString &key = mDict.keyAt(i); 233bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber const AString &value = mDict.valueAt(i); 234bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 235bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (key == AString("_")) { 236bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber continue; 237bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 238bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 239bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append(key); 240bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append(": "); 241bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append(value); 242bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append("\n"); 243bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 244bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 245bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append("\n"); 246bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber line.append(mContent); 247bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 248bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return line; 249bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 250bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 251bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static 252bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::GetAttribute( 253bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber const char *s, const char *key, AString *value) { 254bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber value->clear(); 255bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 256bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t keyLen = strlen(key); 257bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 258bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber for (;;) { 259bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber while (isspace(*s)) { 260bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber ++s; 261bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 262bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 263bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber const char *colonPos = strchr(s, ';'); 264bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 265bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber size_t len = 266bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 267bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 268bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 269bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 270bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return true; 271bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 272bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 273bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (colonPos == NULL) { 274bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 275bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 276bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 277bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber s = colonPos + 1; 278bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 279bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 280bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 281bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static 282bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::GetInt32Attribute( 283bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber const char *s, const char *key, int32_t *value) { 284bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber AString stringValue; 285bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (!GetAttribute(s, key, &stringValue)) { 286bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *value = 0; 287bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 288bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 289bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 290bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber char *end; 291bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *value = strtol(stringValue.c_str(), &end, 10); 292bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 293bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber if (end == stringValue.c_str() || *end != '\0') { 294bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *value = 0; 295bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return false; 296bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber } 297bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 298bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber return true; 299bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} 300bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 301bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber} // namespace android 302bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber 303