debrecords.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: debrecords.cc,v 1.10 2001/03/13 06:51:46 jgg Exp $
  4. /* ######################################################################
  5. Debian Package Records - Parser for debian package records
  6. ##################################################################### */
  7. /*}}}*/
  8. // Include Files /*{{{*/
  9. #include <config.h>
  10. #include <apt-pkg/debrecords.h>
  11. #include <apt-pkg/debindexfile.h>
  12. #include <apt-pkg/strutl.h>
  13. #include <apt-pkg/aptconfiguration.h>
  14. #include <apt-pkg/fileutl.h>
  15. #include <apt-pkg/cacheiterators.h>
  16. #include <apt-pkg/pkgcache.h>
  17. #include <apt-pkg/tagfile.h>
  18. #include <apt-pkg/error.h>
  19. #include <string.h>
  20. #include <algorithm>
  21. #include <sstream>
  22. #include <string>
  23. #include <vector>
  24. #include <langinfo.h>
  25. #include <apti18n.h>
  26. /*}}}*/
  27. using std::string;
  28. // RecordParser::debRecordParser - Constructor /*{{{*/
  29. debRecordParser::debRecordParser(string FileName,pkgCache &Cache) :
  30. debRecordParserBase(), d(NULL), File(FileName, FileFd::ReadOnly, FileFd::Extension),
  31. Tags(&File)
  32. {
  33. }
  34. /*}}}*/
  35. // RecordParser::Jump - Jump to a specific record /*{{{*/
  36. bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
  37. {
  38. if (Ver.end() == true)
  39. return false;
  40. return Tags.Jump(Section,Ver->Offset);
  41. }
  42. bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
  43. {
  44. if (Desc.end() == true)
  45. return false;
  46. return Tags.Jump(Section,Desc->Offset);
  47. }
  48. /*}}}*/
  49. debRecordParser::~debRecordParser() {}
  50. debRecordParserBase::debRecordParserBase() : Parser(), d(NULL) {}
  51. // RecordParserBase::FileName - Return the archive filename on the site /*{{{*/
  52. string debRecordParserBase::FileName()
  53. {
  54. return Section.FindS("Filename");
  55. }
  56. /*}}}*/
  57. // RecordParserBase::Name - Return the package name /*{{{*/
  58. string debRecordParserBase::Name()
  59. {
  60. string Result = Section.FindS("Package");
  61. // Normalize mixed case package names to lower case, like dpkg does
  62. // See Bug#807012 for details
  63. std::transform(Result.begin(), Result.end(), Result.begin(), tolower_ascii);
  64. return Result;
  65. }
  66. /*}}}*/
  67. // RecordParserBase::Display - Return the package homepage /*{{{*/
  68. string debRecordParserBase::Display()
  69. {
  70. string display(Section.FindS("Name"));
  71. if (display.empty())
  72. display = Section.FindS("Maemo-Display-Name");
  73. return display;
  74. }
  75. /*}}}*/
  76. // RecordParserBase::Homepage - Return the package homepage /*{{{*/
  77. string debRecordParserBase::Homepage()
  78. {
  79. return Section.FindS("Homepage");
  80. }
  81. /*}}}*/
  82. // RecordParserBase::Hashes - return the available archive hashes /*{{{*/
  83. HashStringList debRecordParserBase::Hashes() const
  84. {
  85. HashStringList hashes;
  86. for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
  87. {
  88. std::string const hash = Section.FindS(*type);
  89. if (hash.empty() == false)
  90. hashes.push_back(HashString(*type, hash));
  91. }
  92. auto const size = Section.FindULL("Size", 0);
  93. if (size != 0)
  94. hashes.FileSize(size);
  95. return hashes;
  96. }
  97. /*}}}*/
  98. // RecordParserBase::Maintainer - Return the maintainer email /*{{{*/
  99. string debRecordParserBase::Maintainer()
  100. {
  101. return Section.FindS("Maintainer");
  102. }
  103. /*}}}*/
  104. // RecordParserBase::RecordField - Return the value of an arbitrary field /*{{*/
  105. string debRecordParserBase::RecordField(const char *fieldName)
  106. {
  107. return Section.FindS(fieldName);
  108. }
  109. /*}}}*/
  110. // RecordParserBase::ShortDesc - Return a 1 line description /*{{{*/
  111. string debRecordParserBase::ShortDesc(std::string const &lang)
  112. {
  113. string const Res = LongDesc(lang);
  114. if (Res.empty() == true)
  115. return "";
  116. string::size_type const Pos = Res.find('\n');
  117. if (Pos == string::npos)
  118. return Res;
  119. return string(Res,0,Pos);
  120. }
  121. /*}}}*/
  122. // RecordParserBase::LongDesc - Return a longer description /*{{{*/
  123. string debRecordParserBase::LongDesc(std::string const &lang)
  124. {
  125. string orig;
  126. if (lang.empty() == true)
  127. {
  128. std::vector<string> const lang = APT::Configuration::getLanguages();
  129. for (std::vector<string>::const_iterator l = lang.begin();
  130. l != lang.end(); ++l)
  131. {
  132. std::string const tagname = "Description-" + *l;
  133. orig = Section.FindS(tagname.c_str());
  134. if (orig.empty() == false)
  135. break;
  136. else if (*l == "en")
  137. {
  138. orig = Section.FindS("Description");
  139. if (orig.empty() == false)
  140. break;
  141. }
  142. }
  143. if (orig.empty() == true)
  144. orig = Section.FindS("Description");
  145. }
  146. else
  147. {
  148. std::string const tagname = "Description-" + lang;
  149. orig = Section.FindS(tagname.c_str());
  150. if (orig.empty() == true && lang == "en")
  151. orig = Section.FindS("Description");
  152. }
  153. char const * const codeset = nl_langinfo(CODESET);
  154. if (strcmp(codeset,"UTF-8") != 0) {
  155. string dest;
  156. UTF8ToCodeset(codeset, orig, &dest);
  157. return dest;
  158. }
  159. return orig;
  160. }
  161. /*}}}*/
  162. static const char * const SourceVerSeparators = " ()";
  163. // RecordParserBase::SourcePkg - Return the source package name if any /*{{{*/
  164. string debRecordParserBase::SourcePkg()
  165. {
  166. string Res = Section.FindS("Source");
  167. string::size_type Pos = Res.find_first_of(SourceVerSeparators);
  168. if (Pos == string::npos)
  169. return Res;
  170. return string(Res,0,Pos);
  171. }
  172. /*}}}*/
  173. // RecordParserBase::SourceVer - Return the source version number if present /*{{{*/
  174. string debRecordParserBase::SourceVer()
  175. {
  176. string Pkg = Section.FindS("Source");
  177. string::size_type Pos = Pkg.find_first_of(SourceVerSeparators);
  178. if (Pos == string::npos)
  179. return "";
  180. string::size_type VerStart = Pkg.find_first_not_of(SourceVerSeparators, Pos);
  181. if(VerStart == string::npos)
  182. return "";
  183. string::size_type VerEnd = Pkg.find_first_of(SourceVerSeparators, VerStart);
  184. if(VerEnd == string::npos)
  185. // Corresponds to the case of, e.g., "foo (1.2" without a closing
  186. // paren. Be liberal and guess what it means.
  187. return string(Pkg, VerStart);
  188. else
  189. return string(Pkg, VerStart, VerEnd - VerStart);
  190. }
  191. /*}}}*/
  192. // RecordParserBase::GetRec - Return the whole record /*{{{*/
  193. void debRecordParserBase::GetRec(const char *&Start,const char *&Stop)
  194. {
  195. Section.GetSection(Start,Stop);
  196. }
  197. /*}}}*/
  198. // RecordParserBase::Find - Locate a tag /*{{{*/
  199. bool debRecordParserBase::Find(const char *Tag,const char *&Start, const char *&End)
  200. {
  201. return Section.Find(Tag,Start,End);
  202. }
  203. /*}}}*/
  204. debRecordParserBase::~debRecordParserBase() {}
  205. bool debDebFileRecordParser::LoadContent()
  206. {
  207. // load content only once
  208. if (controlContent.empty() == false)
  209. return true;
  210. std::ostringstream content;
  211. if (debDebPkgFileIndex::GetContent(content, debFileName) == false)
  212. return false;
  213. // add two newlines to make sure the scanner finds the section,
  214. // which is usually done by pkgTagFile automatically if needed.
  215. content << "\n\n";
  216. controlContent = content.str();
  217. if (Section.Scan(controlContent.c_str(), controlContent.length(), false) == false)
  218. return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3);
  219. return true;
  220. }
  221. bool debDebFileRecordParser::Jump(pkgCache::VerFileIterator const &) { return LoadContent(); }
  222. bool debDebFileRecordParser::Jump(pkgCache::DescFileIterator const &) { return LoadContent(); }
  223. std::string debDebFileRecordParser::FileName() { return debFileName; }
  224. debDebFileRecordParser::debDebFileRecordParser(std::string FileName) : debRecordParserBase(), d(NULL), debFileName(FileName) {}
  225. debDebFileRecordParser::~debDebFileRecordParser() {}