debrecords.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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(), File(FileName, FileFd::ReadOnly, FileFd::Extension),
  31. Tags(&File, std::max(Cache.Head().MaxVerFileSize, Cache.Head().MaxDescFileSize) + 200)
  32. {
  33. }
  34. /*}}}*/
  35. // RecordParser::Jump - Jump to a specific record /*{{{*/
  36. bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
  37. {
  38. return Tags.Jump(Section,Ver->Offset);
  39. }
  40. bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
  41. {
  42. return Tags.Jump(Section,Desc->Offset);
  43. }
  44. /*}}}*/
  45. debRecordParser::~debRecordParser() {}
  46. debRecordParserBase::debRecordParserBase() : Parser() {}
  47. // RecordParserBase::FileName - Return the archive filename on the site /*{{{*/
  48. string debRecordParserBase::FileName()
  49. {
  50. return Section.FindS("Filename");
  51. }
  52. /*}}}*/
  53. // RecordParserBase::Name - Return the package name /*{{{*/
  54. string debRecordParserBase::Name()
  55. {
  56. return Section.FindS("Package");
  57. }
  58. /*}}}*/
  59. // RecordParserBase::Homepage - Return the package homepage /*{{{*/
  60. string debRecordParserBase::Homepage()
  61. {
  62. return Section.FindS("Homepage");
  63. }
  64. /*}}}*/
  65. // RecordParserBase::Hashes - return the available archive hashes /*{{{*/
  66. HashStringList debRecordParserBase::Hashes() const
  67. {
  68. HashStringList hashes;
  69. for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
  70. {
  71. std::string const hash = Section.FindS(*type);
  72. if (hash.empty() == false)
  73. hashes.push_back(HashString(*type, hash));
  74. }
  75. return hashes;
  76. }
  77. /*}}}*/
  78. // RecordParserBase::Maintainer - Return the maintainer email /*{{{*/
  79. string debRecordParserBase::Maintainer()
  80. {
  81. return Section.FindS("Maintainer");
  82. }
  83. /*}}}*/
  84. // RecordParserBase::RecordField - Return the value of an arbitrary field /*{{*/
  85. string debRecordParserBase::RecordField(const char *fieldName)
  86. {
  87. return Section.FindS(fieldName);
  88. }
  89. /*}}}*/
  90. // RecordParserBase::ShortDesc - Return a 1 line description /*{{{*/
  91. string debRecordParserBase::ShortDesc(std::string const &lang)
  92. {
  93. string const Res = LongDesc(lang);
  94. if (Res.empty() == true)
  95. return "";
  96. string::size_type const Pos = Res.find('\n');
  97. if (Pos == string::npos)
  98. return Res;
  99. return string(Res,0,Pos);
  100. }
  101. /*}}}*/
  102. // RecordParserBase::LongDesc - Return a longer description /*{{{*/
  103. string debRecordParserBase::LongDesc(std::string const &lang)
  104. {
  105. string orig;
  106. if (lang.empty() == true)
  107. {
  108. std::vector<string> const lang = APT::Configuration::getLanguages();
  109. for (std::vector<string>::const_iterator l = lang.begin();
  110. l != lang.end(); ++l)
  111. {
  112. std::string const tagname = "Description-" + *l;
  113. orig = Section.FindS(tagname.c_str());
  114. if (orig.empty() == false)
  115. break;
  116. else if (*l == "en")
  117. {
  118. orig = Section.FindS("Description");
  119. if (orig.empty() == false)
  120. break;
  121. }
  122. }
  123. if (orig.empty() == true)
  124. orig = Section.FindS("Description");
  125. }
  126. else
  127. {
  128. std::string const tagname = "Description-" + lang;
  129. orig = Section.FindS(tagname.c_str());
  130. if (orig.empty() == true && lang == "en")
  131. orig = Section.FindS("Description");
  132. }
  133. char const * const codeset = nl_langinfo(CODESET);
  134. if (strcmp(codeset,"UTF-8") != 0) {
  135. string dest;
  136. UTF8ToCodeset(codeset, orig, &dest);
  137. return dest;
  138. }
  139. return orig;
  140. }
  141. /*}}}*/
  142. static const char * const SourceVerSeparators = " ()";
  143. // RecordParserBase::SourcePkg - Return the source package name if any /*{{{*/
  144. string debRecordParserBase::SourcePkg()
  145. {
  146. string Res = Section.FindS("Source");
  147. string::size_type Pos = Res.find_first_of(SourceVerSeparators);
  148. if (Pos == string::npos)
  149. return Res;
  150. return string(Res,0,Pos);
  151. }
  152. /*}}}*/
  153. // RecordParserBase::SourceVer - Return the source version number if present /*{{{*/
  154. string debRecordParserBase::SourceVer()
  155. {
  156. string Pkg = Section.FindS("Source");
  157. string::size_type Pos = Pkg.find_first_of(SourceVerSeparators);
  158. if (Pos == string::npos)
  159. return "";
  160. string::size_type VerStart = Pkg.find_first_not_of(SourceVerSeparators, Pos);
  161. if(VerStart == string::npos)
  162. return "";
  163. string::size_type VerEnd = Pkg.find_first_of(SourceVerSeparators, VerStart);
  164. if(VerEnd == string::npos)
  165. // Corresponds to the case of, e.g., "foo (1.2" without a closing
  166. // paren. Be liberal and guess what it means.
  167. return string(Pkg, VerStart);
  168. else
  169. return string(Pkg, VerStart, VerEnd - VerStart);
  170. }
  171. /*}}}*/
  172. // RecordParserBase::GetRec - Return the whole record /*{{{*/
  173. void debRecordParserBase::GetRec(const char *&Start,const char *&Stop)
  174. {
  175. Section.GetSection(Start,Stop);
  176. }
  177. /*}}}*/
  178. debRecordParserBase::~debRecordParserBase() {}
  179. bool debDebFileRecordParser::LoadContent()
  180. {
  181. // load content only once
  182. if (controlContent.empty() == false)
  183. return true;
  184. std::ostringstream content;
  185. if (debDebPkgFileIndex::GetContent(content, debFileName) == false)
  186. return false;
  187. // add two newlines to make sure the scanner finds the section,
  188. // which is usually done by pkgTagFile automatically if needed.
  189. content << "\n\n";
  190. controlContent = content.str();
  191. if (Section.Scan(controlContent.c_str(), controlContent.length()) == false)
  192. return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3);
  193. return true;
  194. }
  195. bool debDebFileRecordParser::Jump(pkgCache::VerFileIterator const &) { return LoadContent(); }
  196. bool debDebFileRecordParser::Jump(pkgCache::DescFileIterator const &) { return LoadContent(); }
  197. std::string debDebFileRecordParser::FileName() { return debFileName; }
  198. debDebFileRecordParser::debDebFileRecordParser(std::string FileName) : debRecordParserBase(), debFileName(FileName) {}
  199. debDebFileRecordParser::~debDebFileRecordParser() {}