/* */ #include "MetaFileUtil.h" #include "Data.h" #include "Dictionary.h" #include "List.h" #include "File.h" #include "DlAbortEx.h" #include "message.h" #include namespace aria2 { MetaEntry* MetaFileUtil::parseMetaFile(const std::string& file) { File f(file); int32_t len = f.size(); char* buf = new char[len]; FILE* fp = fopen(file.c_str(), "r+b"); try { if(fp == NULL) { throw new DlAbortEx("cannot open metainfo file"); } if(fread(buf, len, 1, fp) != 1) { fclose(fp); throw new DlAbortEx("cannot read metainfo"); } fclose(fp); fp = NULL; MetaEntry* entry = bdecoding(buf, len); delete [] buf; return entry; } catch(RecoverableException* ex) { delete [] buf; if(fp != NULL) { fclose(fp); } throw; } } MetaEntry* MetaFileUtil::bdecoding(const char* buf, int32_t len) { MetaEntry* entry = NULL; try{ const char* p = buf; const char* end = buf+len; entry = bdecodingR(&p, end); return entry; } catch(RecoverableException* ex) { if(entry != NULL) { delete entry; } throw; } } MetaEntry* MetaFileUtil::bdecodingR(const char** pp, const char* end) { if(*pp >= end) { throw new DlAbortEx("Malformed metainfo"); } MetaEntry* e; switch(**pp) { case 'd': (*pp)++; e = parseDictionaryTree(pp, end); break; case 'l': (*pp)++; e = parseListTree(pp, end); break; case 'i': (*pp)++; e = decodeInt(pp, end); break; default: e = decodeWord(pp, end); } return e; } Dictionary* MetaFileUtil::parseDictionaryTree(const char** pp, const char* end) { if(*pp >= end) { throw new DlAbortEx("Malformed metainfo"); } Dictionary* dic = new Dictionary(); try { while(1) { if(**pp == 'e') { (*pp)++; break; } std::string name = decodeWordAsString(pp, end); MetaEntry* e = bdecodingR(pp, end); dic->put(name, e); } return dic; } catch(RecoverableException* ex) { delete dic; throw; } } List* MetaFileUtil::parseListTree(const char** pp, const char* end) { if(*pp >= end) { throw new DlAbortEx("Malformed metainfo"); } List* lis = new List(); try { while(1) { if(**pp == 'e') { (*pp)++; break; } MetaEntry* e = bdecodingR(pp, end); lis->add(e); } return lis; } catch(RecoverableException* ex) { delete lis; throw; } } Data* MetaFileUtil::decodeInt(const char** pp, const char* end) { if(*pp >= end) { throw new DlAbortEx(EX_MALFORMED_META_INFO); } char* endTerm = (char*)memchr(*pp, 'e', end-*pp); // TODO if endTerm is null if(endTerm == NULL) { throw new DlAbortEx(EX_MALFORMED_META_INFO); } int32_t numSize = endTerm-*pp; Data* data = new Data(*pp, numSize, true); *pp += numSize+1; return data; } Data* MetaFileUtil::decodeWord(const char** pp, const char* end) { if(*pp >= end) { throw new DlAbortEx("Malformed metainfo"); } char* delim = (char*)memchr(*pp, ':', end-*pp); // TODO if delim is null if(delim == *pp || delim == NULL) { throw new DlAbortEx(EX_MALFORMED_META_INFO); } int32_t numSize = delim-*pp; char* temp = new char[numSize+1]; memcpy(temp, *pp, numSize); temp[numSize] = '\0'; char* endptr; int32_t size = strtol(temp, &endptr, 10); if(*endptr != '\0') { delete [] temp; throw new DlAbortEx(EX_MALFORMED_META_INFO); } delete [] temp; if(delim+1+size > end) { throw new DlAbortEx(EX_MALFORMED_META_INFO); } Data* data = new Data(delim+1, size); *pp = delim+1+size; return data; } std::string MetaFileUtil::decodeWordAsString(const char** pp, const char* end) { Data* data = decodeWord(pp, end); std::string str = data->toString(); delete data; return str; } } // namespace aria2