toolkit/components/url-classifier/content/wireformat.js

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6 // A class that serializes and deserializes opaque key/value string to
     7 // string maps to/from maps (trtables). It knows how to create
     8 // trtables from the serialized format, so it also understands
     9 // meta-information like the name of the table and the table's
    10 // version. See docs for the protocol description.
    11 // 
    12 // TODO: wireformatreader: if you have multiple updates for one table
    13 //       in a call to deserialize, the later ones will be merged 
    14 //       (all but the last will be ignored). To fix, merge instead
    15 //       of replace when you have an existing table, and only do so once.
    16 // TODO must have blank line between successive types -- problem?
    17 // TODO doesn't tolerate blank lines very well
    18 //
    19 // Maybe: These classes could use a LOT more cleanup, but it's not a
    20 //       priority at the moment. For example, the tablesData/Known
    21 //       maps should be combined into a single object, the parser
    22 //       for a given type should be separate from the version info,
    23 //       and there should be synchronous interfaces for testing.
    26 /**
    27  * A class that knows how to serialize and deserialize meta-information.
    28  * This meta information is the table name and version number, and 
    29  * in its serialized form looks like the first line below:
    30  * 
    31  * [name-of-table X.Y update?]                
    32  * ...key/value pairs to add or delete follow...
    33  * <blank line ends the table>
    34  *
    35  * The X.Y is the version number and the optional "update" token means 
    36  * that the table is a differential from the curent table the extension
    37  * has. Its absence means that this is a full, new table.
    38  */
    39 function PROT_VersionParser(type, opt_major, opt_minor, opt_requireMac) {
    40   this.debugZone = "versionparser";
    41   this.type = type;
    42   this.major = 0;
    43   this.minor = 0;
    45   this.badHeader = false;
    47   // Should the wireformatreader compute a mac?
    48   this.mac = false;
    49   this.macval = "";
    50   this.macFailed = false;
    51   this.requireMac = !!opt_requireMac;
    53   this.update = false;
    54   this.needsUpdate = false;  // used by ListManager to determine update policy
    55   // Used by ListerManager to see if we have read data for this table from
    56   // disk.  Once we read a table from disk, we are not going to do so again
    57   // but instead update remotely if necessary.
    58   this.didRead = false;
    59   if (opt_major)
    60     this.major = parseInt(opt_major);
    61   if (opt_minor)
    62     this.minor = parseInt(opt_minor);
    63 }
    65 /** Import the version information from another VersionParser
    66  * @params version a version parser object
    67  */
    68 PROT_VersionParser.prototype.ImportVersion = function(version) {
    69   this.major = version.major;
    70   this.minor = version.minor;
    72   this.mac = version.mac;
    73   this.macFailed = version.macFailed;
    74   this.macval = version.macval;
    75   // Don't set requireMac, since we create vparsers from scratch and doesn't
    76   // know about it
    77 }
    79 /** 
    80  * Creates a string like [goog-white-black 1.1] from internal information
    81  * 
    82  * @returns String
    83  */
    84 PROT_VersionParser.prototype.toString = function() {
    85   var s = "[" + this.type + " " + this.major + "." + this.minor + "]";
    86   return s;
    87 }
    89 /**
    90  * Creates a string like 1.123 with the version number.  This is the
    91  * format we store in prefs.
    92  * @return String
    93  */
    94 PROT_VersionParser.prototype.versionString = function() {
    95   return this.major + "." + this.minor;
    96 }
    98 /** 
    99  * Creates a string like 1:1 from internal information used for
   100  * fetching updates from the server. Called by the listmanager.
   101  * 
   102  * @returns String
   103  */
   104 PROT_VersionParser.prototype.toUrl = function() {
   105   return this.major + ":" + this.minor;
   106 }
   108 /**
   109  * Process the old format, [type major.minor [update]]
   110  *
   111  * @returns true if the string could be parsed, false otherwise
   112  */
   113 PROT_VersionParser.prototype.processOldFormat_ = function(line) {
   114   if (line[0] != '[' || line.slice(-1) != ']')
   115     return false;
   117   var description = line.slice(1, -1);
   119   // Get the type name and version number of this table
   120   var tokens = description.split(" ");
   121   this.type = tokens[0];
   122   var majorminor = tokens[1].split(".");
   123   this.major = parseInt(majorminor[0]);
   124   this.minor = parseInt(majorminor[1]);
   125   if (isNaN(this.major) || isNaN(this.minor))
   126     return false;
   128   if (tokens.length >= 3) {
   129      this.update = tokens[2] == "update";
   130   }
   132   return true;
   133 }
   135 /**
   136  * Takes a string like [name-of-table 1.1 [update]][mac=MAC] and figures out the
   137  * type and corresponding version numbers.
   138  * @returns true if the string could be parsed, false otherwise
   139  */
   140 PROT_VersionParser.prototype.fromString = function(line) {
   141   G_Debug(this, "Calling fromString with line: " + line);
   142   if (line[0] != '[' || line.slice(-1) != ']')
   143     return false;
   145   // There could be two [][], so take care of it
   146   var secondBracket = line.indexOf('[', 1);
   147   var firstPart = null;
   148   var secondPart = null;
   150   if (secondBracket != -1) {
   151     firstPart = line.substring(0, secondBracket);
   152     secondPart = line.substring(secondBracket);
   153     G_Debug(this, "First part: " + firstPart + " Second part: " + secondPart);
   154   } else {
   155     firstPart = line;
   156     G_Debug(this, "Old format: " + firstPart);
   157   }
   159   if (!this.processOldFormat_(firstPart))
   160     return false;
   162   if (secondPart && !this.processOptTokens_(secondPart))
   163     return false;
   165   return true;
   166 }
   168 /**
   169  * Process optional tokens
   170  *
   171  * @param line A string [token1=val1 token2=val2...]
   172  * @returns true if the string could be parsed, false otherwise
   173  */
   174 PROT_VersionParser.prototype.processOptTokens_ = function(line) {
   175   if (line[0] != '[' || line.slice(-1) != ']')
   176     return false;
   177   var description = line.slice(1, -1);
   178   // Get the type name and version number of this table
   179   var tokens = description.split(" ");
   181   for (var i = 0; i < tokens.length; i++) {
   182     G_Debug(this, "Processing optional token: " + tokens[i]);
   183     var tokenparts = tokens[i].split("=");
   184     switch(tokenparts[0]){
   185     case "mac":
   186       this.mac = true;
   187       if (tokenparts.length < 2) {
   188         G_Debug(this, "Found mac flag but not mac value!");
   189         return false;
   190       }
   191       // The mac value may have "=" in it, so we can't just use tokenparts[1].
   192       // Instead, just take the rest of tokens[i] after the first "="
   193       this.macval = tokens[i].substr(tokens[i].indexOf("=")+1);
   194       break;
   195     default:
   196       G_Debug(this, "Found unrecognized token: " + tokenparts[0]);
   197       break;
   198     }
   199   }
   201   return true;
   202 }
   204 #ifdef DEBUG
   205 function TEST_PROT_WireFormat() {
   206   if (G_GDEBUG) {
   207     var z = "versionparser UNITTEST";
   208     G_Debug(z, "Starting");
   210     var vp = new PROT_VersionParser("dummy");
   211     G_Assert(z, vp.fromString("[foo-bar-url 1.234]"),
   212              "failed to parse old format");
   213     G_Assert(z, "foo-bar-url" == vp.type, "failed to parse type");
   214     G_Assert(z, "1" == vp.major, "failed to parse major");
   215     G_Assert(z, "234" == vp.minor, "failed to parse minor");
   217     vp = new PROT_VersionParser("dummy");
   218     G_Assert(z, vp.fromString("[foo-bar-url 1.234][mac=567]"),
   219              "failed to parse new format");
   220     G_Assert(z, "foo-bar-url" == vp.type, "failed to parse type");
   221     G_Assert(z, "1" == vp.major, "failed to parse major");
   222     G_Assert(z, "234" == vp.minor, "failed to parse minor");
   223     G_Assert(z, true == vp.mac, "failed to parse mac");
   224     G_Assert(z, "567" == vp.macval, "failed to parse macval");
   226     G_Debug(z, "PASSED");
   227   }
   228 }
   229 #endif

mercurial