| 1 | // -*- mode: cpp; mode: fold -*- |
| 2 | // Description /*{{{*/ |
| 3 | /* ###################################################################### |
| 4 | |
| 5 | Fast scanner for RFC-822 type header information |
| 6 | |
| 7 | This parser handles Debian package files (and others). Their form is |
| 8 | RFC-822 type header fields in groups separated by a blank line. |
| 9 | |
| 10 | The parser reads the file and provides methods to step linearly |
| 11 | over it or to jump to a pre-recorded start point and read that record. |
| 12 | |
| 13 | A second class is used to perform pre-parsing of the record. It works |
| 14 | by indexing the start of each header field and providing lookup |
| 15 | functions for header fields. |
| 16 | |
| 17 | ##################################################################### */ |
| 18 | /*}}}*/ |
| 19 | #ifndef PKGLIB_TAGFILE_H |
| 20 | #define PKGLIB_TAGFILE_H |
| 21 | |
| 22 | #include <apt-pkg/macros.h> |
| 23 | |
| 24 | #include <stdio.h> |
| 25 | #include <stdint.h> |
| 26 | |
| 27 | #include <string> |
| 28 | #include <vector> |
| 29 | #include <list> |
| 30 | |
| 31 | #ifndef APT_8_CLEANER_HEADERS |
| 32 | #include <apt-pkg/fileutl.h> |
| 33 | #endif |
| 34 | |
| 35 | class FileFd; |
| 36 | class pkgTagSectionPrivate; |
| 37 | |
| 38 | class pkgTagSection |
| 39 | { |
| 40 | const char *Section; |
| 41 | unsigned int AlphaIndexes[0x100]; |
| 42 | |
| 43 | pkgTagSectionPrivate * const d; |
| 44 | |
| 45 | protected: |
| 46 | const char *Stop; |
| 47 | |
| 48 | public: |
| 49 | |
| 50 | inline bool operator ==(const pkgTagSection &rhs) {return Section == rhs.Section;}; |
| 51 | inline bool operator !=(const pkgTagSection &rhs) {return Section != rhs.Section;}; |
| 52 | |
| 53 | bool Find(const char *Tag,const char *&Start, const char *&End) const; |
| 54 | bool Find(const char *Tag,unsigned int &Pos) const; |
| 55 | std::string FindS(const char *Tag) const; |
| 56 | std::string FindRawS(const char *Tag) const; |
| 57 | signed int FindI(const char *Tag,signed long Default = 0) const; |
| 58 | bool FindB(const char *Tag, bool const &Default = false) const; |
| 59 | unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const; |
| 60 | bool FindFlag(const char * const Tag,uint8_t &Flags, |
| 61 | uint8_t const Flag) const; |
| 62 | bool static FindFlag(uint8_t &Flags, uint8_t const Flag, |
| 63 | const char* const Start, const char* const Stop); |
| 64 | bool FindFlag(const char *Tag,unsigned long &Flags, |
| 65 | unsigned long Flag) const; |
| 66 | bool static FindFlag(unsigned long &Flags, unsigned long Flag, |
| 67 | const char* Start, const char* Stop); |
| 68 | |
| 69 | /** \brief searches the boundaries of the current section |
| 70 | * |
| 71 | * While parameter Start marks the beginning of the section, this method |
| 72 | * will search for the first double newline in the data stream which marks |
| 73 | * the end of the section. It also does a first pass over the content of |
| 74 | * the section parsing it as encountered for processing later on by Find |
| 75 | * |
| 76 | * @param Start is the beginning of the section |
| 77 | * @param MaxLength is the size of valid data in the stream pointed to by Start |
| 78 | * @param Restart if enabled internal state will be cleared, otherwise it is |
| 79 | * assumed that now more data is available in the stream and the parsing will |
| 80 | * start were it encountered insufficent data the last time. |
| 81 | * |
| 82 | * @return \b true if section end was found, \b false otherwise. |
| 83 | * Beware that internal state will be inconsistent if \b false is returned! |
| 84 | */ |
| 85 | APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart = true); |
| 86 | |
| 87 | inline unsigned long size() const {return Stop - Section;}; |
| 88 | void Trim(); |
| 89 | virtual void TrimRecord(bool BeforeRecord, const char* &End); |
| 90 | |
| 91 | /** \brief amount of Tags in the current section |
| 92 | * |
| 93 | * Note: if a Tag is mentioned repeatly it will be counted multiple |
| 94 | * times, but only the last occurrence is available via Find methods. |
| 95 | */ |
| 96 | unsigned int Count() const; |
| 97 | bool Exists(const char* const Tag) const; |
| 98 | |
| 99 | void Get(const char *&Start,const char *&Stop,unsigned int I) const; |
| 100 | |
| 101 | inline void GetSection(const char *&Start,const char *&Stop) const |
| 102 | { |
| 103 | Start = Section; |
| 104 | Stop = this->Stop; |
| 105 | }; |
| 106 | |
| 107 | pkgTagSection(); |
| 108 | virtual ~pkgTagSection(); |
| 109 | |
| 110 | struct Tag |
| 111 | { |
| 112 | enum ActionType { REMOVE, RENAME, REWRITE } Action; |
| 113 | std::string Name; |
| 114 | std::string Data; |
| 115 | |
| 116 | static Tag Remove(std::string const &Name); |
| 117 | static Tag Rename(std::string const &OldName, std::string const &NewName); |
| 118 | static Tag Rewrite(std::string const &Name, std::string const &Data); |
| 119 | private: |
| 120 | Tag(ActionType const Action, std::string const &Name, std::string const &Data) : |
| 121 | Action(Action), Name(Name), Data(Data) {} |
| 122 | }; |
| 123 | |
| 124 | /** Write this section (with optional rewrites) to a file |
| 125 | * |
| 126 | * @param File to write the section to |
| 127 | * @param Order in which tags should appear in the file |
| 128 | * @param Rewrite is a set of tags to be renamed, rewritten and/or removed |
| 129 | * @return \b true if successful, otherwise \b false |
| 130 | */ |
| 131 | bool Write(FileFd &File, char const * const * const Order = NULL, std::vector<Tag> const &Rewrite = std::vector<Tag>()) const; |
| 132 | }; |
| 133 | |
| 134 | |
| 135 | /* For user generated file the parser should be a bit more relaxed in exchange |
| 136 | for being a bit slower to allow comments and new lines all over the place */ |
| 137 | class pkgUserTagSection : public pkgTagSection |
| 138 | { |
| 139 | virtual void TrimRecord(bool BeforeRecord, const char* &End) APT_OVERRIDE; |
| 140 | }; |
| 141 | |
| 142 | class pkgTagFilePrivate; |
| 143 | class pkgTagFile |
| 144 | { |
| 145 | pkgTagFilePrivate * const d; |
| 146 | |
| 147 | APT_HIDDEN bool Fill(); |
| 148 | APT_HIDDEN bool Resize(); |
| 149 | APT_HIDDEN bool Resize(unsigned long long const newSize); |
| 150 | |
| 151 | public: |
| 152 | |
| 153 | bool Step(pkgTagSection &Section); |
| 154 | unsigned long Offset(); |
| 155 | bool Jump(pkgTagSection &Tag,unsigned long long Offset); |
| 156 | |
| 157 | void Init(FileFd * const F,unsigned long long const Size = 32*1024); |
| 158 | |
| 159 | pkgTagFile(FileFd * const F,unsigned long long Size = 32*1024); |
| 160 | virtual ~pkgTagFile(); |
| 161 | }; |
| 162 | |
| 163 | extern const char **TFRewritePackageOrder; |
| 164 | extern const char **TFRewriteSourceOrder; |
| 165 | |
| 166 | // Use pkgTagSection::Tag and pkgTagSection::Write() instead |
| 167 | APT_IGNORE_DEPRECATED_PUSH |
| 168 | struct APT_DEPRECATED TFRewriteData |
| 169 | { |
| 170 | const char *Tag; |
| 171 | const char *Rewrite; |
| 172 | const char *NewTag; |
| 173 | }; |
| 174 | APT_DEPRECATED bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], |
| 175 | TFRewriteData *Rewrite); |
| 176 | APT_IGNORE_DEPRECATED_POP |
| 177 | |
| 178 | #endif |