Browse Source

support coreapi_set_ver token

David Rose 15 years ago
parent
commit
634f6137cd

+ 109 - 17
direct/src/plugin_npapi/ppInstance.cxx

@@ -72,8 +72,15 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode,
         v = "";
       }
 
+      // Make the token lowercase, since HTML is case-insensitive but
+      // we're not.
+      string keyword;
+      for (const char *p = argn[i]; *p; ++p) {
+        keyword += tolower(*p);
+      }
+
       P3D_token token;
-      token._keyword = strdup(argn[i]);
+      token._keyword = strdup(keyword.c_str());
       token._value = strdup(v);
       _tokens.push_back(token);
     }
@@ -1238,6 +1245,24 @@ read_contents_file(const string &contents_filename, bool fresh_download) {
     return false;
   }
 
+  // Check the coreapi_set_ver token.  If it is given, it specifies a
+  // minimum Core API version number we expect to find.  If we didn't
+  // find that number, perhaps our contents.xml is out of date.
+  string coreapi_set_ver = lookup_token("coreapi_set_ver");
+  if (!coreapi_set_ver.empty()) {
+    nout << "Instance asked for Core API set_ver " << coreapi_set_ver
+         << ", we found " << _coreapi_set_ver << "\n";
+    // But don't bother if we just freshly downloaded it.
+    if (!fresh_download) {
+      if (compare_seq(coreapi_set_ver, _coreapi_set_ver) > 0) {
+        // The requested set_ver value is higher than the one we have on
+        // file; our contents.xml file must be out of date after all.
+        nout << "expiring contents.xml\n";
+        _contents_expiration = 0;
+      }
+    }
+  }
+
   // Success.  Now save the file in its proper place.
   string standard_filename = _root_dir + "/contents.xml";
 
@@ -1809,6 +1834,88 @@ copy_file(const string &from_filename, const string &to_filename) {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::lookup_token
+//       Access: Private
+//  Description: Returns the value associated with the first
+//               appearance of the named token, or empty string if the
+//               token does not appear.
+////////////////////////////////////////////////////////////////////
+string PPInstance::
+lookup_token(const string &keyword) const {
+  Tokens::const_iterator ti;
+  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
+    if (keyword == (*ti)._keyword) {
+      return (*ti)._value;
+    }
+  }
+
+  return string();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::compare_seq
+//       Access: Private, Static
+//  Description: Compares the two dotted-integer sequence values
+//               numerically.  Returns -1 if seq_a sorts first, 1 if
+//               seq_b sorts first, 0 if they are equivalent.
+////////////////////////////////////////////////////////////////////
+int PPInstance::
+compare_seq(const string &seq_a, const string &seq_b) {
+  const char *num_a = seq_a.c_str();
+  const char *num_b = seq_b.c_str();
+  int comp = compare_seq_int(num_a, num_b);
+  while (comp == 0) {
+    if (*num_a != '.') {
+      if (*num_b != '.') {
+        // Both strings ran out together.
+        return 0;
+      }
+      // a ran out first.
+      return -1;
+    } else if (*num_b != '.') {
+      // b ran out first.
+      return 1;
+    }
+
+    // Increment past the dot.
+    ++num_a;
+    ++num_b;
+    comp = compare_seq(num_a, num_b);
+  }
+
+  return comp;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::compare_seq_int
+//       Access: Private, Static
+//  Description: Numerically compares the formatted integer value at
+//               num_a with num_b.  Increments both num_a and num_b to
+//               the next character following the valid integer.
+////////////////////////////////////////////////////////////////////
+int PPInstance::
+compare_seq_int(const char *&num_a, const char *&num_b) {
+  long int a;
+  char *next_a;
+  long int b;
+  char *next_b;
+
+  a = strtol((char *)num_a, &next_a, 10);
+  b = strtol((char *)num_b, &next_b, 10);
+
+  num_a = next_a;
+  num_b = next_b;
+
+  if (a < b) {
+    return -1;
+  } else if (b < a) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PPInstance::set_failed
 //       Access: Private
@@ -1824,23 +1931,8 @@ set_failed() {
     nout << "Plugin failed.\n";
     stop_outstanding_streams();
 
-    string expression;
     // Look for the "onpluginfail" token.
-    Tokens::iterator ti;
-    for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
-      if ((*ti)._keyword != NULL && (*ti)._value != NULL) {
-        // Make the token lowercase, since HTML is case-insensitive but
-        // we're not.
-        string keyword;
-        for (const char *p = (*ti)._keyword; *p; ++p) {
-          keyword += tolower(*p);
-        }
-        if (keyword == "onpluginfail") {
-          expression = (*ti)._value;
-          break;
-        }
-      }
-    }
+    string expression = lookup_token("onpluginfail");
 
     if (!expression.empty()) {
       // Now attempt to evaluate the expression.

+ 4 - 0
direct/src/plugin_npapi/ppInstance.h

@@ -94,6 +94,10 @@ private:
   void cleanup_window();
   bool copy_file(const string &from_filename, const string &to_filename);
 
+  string lookup_token(const string &keyword) const;
+  static int compare_seq(const string &seq_a, const string &seq_b);
+  static int compare_seq_int(const char *&num_a, const char *&num_b);
+
   void set_failed();
 
   static void handle_request_loop();

+ 18 - 0
direct/src/plugin_standalone/panda3d.cxx

@@ -536,6 +536,24 @@ read_contents_file(const Filename &contents_filename, bool fresh_download) {
     return false;
   }
 
+  // Check the coreapi_set_ver token.  If it is given, it specifies a
+  // minimum Core API version number we expect to find.  If we didn't
+  // find that number, perhaps our contents.xml is out of date.
+  string coreapi_set_ver = lookup_token("coreapi_set_ver");
+  if (!coreapi_set_ver.empty()) {
+    nout << "Instance asked for Core API set_ver " << coreapi_set_ver
+         << ", we found " << _coreapi_set_ver << "\n";
+    // But don't bother if we just freshly downloaded it.
+    if (!fresh_download) {
+      if (compare_seq(coreapi_set_ver, _coreapi_set_ver) > 0) {
+        // The requested set_ver value is higher than the one we have on
+        // file; our contents.xml file must be out of date after all.
+        nout << "expiring contents.xml\n";
+        _contents_expiration = 0;
+      }
+    }
+  }
+
   // Success.  Now copy the file into place.
   Filename standard_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
   if (fresh_download) {

+ 92 - 8
direct/src/plugin_standalone/panda3dBase.cxx

@@ -434,19 +434,21 @@ delete_instance(P3D_instance *inst) {
 //               on failure.
 ////////////////////////////////////////////////////////////////////
 bool Panda3DBase::
-parse_token(char *arg) {
-  char *equals = strchr(arg, '=');
+parse_token(const char *arg) {
+  const char *equals = strchr(arg, '=');
   if (equals == NULL) {
     return false;
   }
 
-  // Directly munge the C string to truncate it at the equals sign.
-  // Classic C tricks.
-  *equals = '\0';
+  // By convention, the keyword is always lowercase.
+  string keyword;
+  for (const char *p = arg; p < equals; ++p) {
+    keyword += tolower(*p);
+  }
+
   P3D_token token;
-  token._keyword = strdup(arg);
+  token._keyword = strdup(keyword.c_str());
   token._value = strdup(equals + 1);
-  *equals = '=';
 
   _tokens.push_back(token);
 
@@ -460,7 +462,7 @@ parse_token(char *arg) {
 //               Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool Panda3DBase::
-parse_int_pair(char *arg, int &x, int &y) {
+parse_int_pair(const char *arg, int &x, int &y) {
   char *endptr;
   x = strtol(arg, &endptr, 10);
   if (*endptr == ',') {
@@ -474,6 +476,88 @@ parse_int_pair(char *arg, int &x, int &y) {
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Panda3DBase::lookup_token
+//       Access: Protected
+//  Description: Returns the value associated with the first
+//               appearance of the named token, or empty string if the
+//               token does not appear.
+////////////////////////////////////////////////////////////////////
+string Panda3DBase::
+lookup_token(const string &keyword) const {
+  Tokens::const_iterator ti;
+  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
+    if (keyword == (*ti)._keyword) {
+      return (*ti)._value;
+    }
+  }
+
+  return string();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Panda3DBase::compare_seq
+//       Access: Protected, Static
+//  Description: Compares the two dotted-integer sequence values
+//               numerically.  Returns -1 if seq_a sorts first, 1 if
+//               seq_b sorts first, 0 if they are equivalent.
+////////////////////////////////////////////////////////////////////
+int Panda3DBase::
+compare_seq(const string &seq_a, const string &seq_b) {
+  const char *num_a = seq_a.c_str();
+  const char *num_b = seq_b.c_str();
+  int comp = compare_seq_int(num_a, num_b);
+  while (comp == 0) {
+    if (*num_a != '.') {
+      if (*num_b != '.') {
+        // Both strings ran out together.
+        return 0;
+      }
+      // a ran out first.
+      return -1;
+    } else if (*num_b != '.') {
+      // b ran out first.
+      return 1;
+    }
+
+    // Increment past the dot.
+    ++num_a;
+    ++num_b;
+    comp = compare_seq(num_a, num_b);
+  }
+
+  return comp;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Panda3DBase::compare_seq_int
+//       Access: Protected, Static
+//  Description: Numerically compares the formatted integer value at
+//               num_a with num_b.  Increments both num_a and num_b to
+//               the next character following the valid integer.
+////////////////////////////////////////////////////////////////////
+int Panda3DBase::
+compare_seq_int(const char *&num_a, const char *&num_b) {
+  long int a;
+  char *next_a;
+  long int b;
+  char *next_b;
+
+  a = strtol((char *)num_a, &next_a, 10);
+  b = strtol((char *)num_b, &next_b, 10);
+
+  num_a = next_a;
+  num_b = next_b;
+
+  if (a < b) {
+    return -1;
+  } else if (b < a) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Panda3DBase::is_url
 //       Access: Protected, Static

+ 5 - 2
direct/src/plugin_standalone/panda3dBase.h

@@ -53,8 +53,11 @@ protected:
                   char **args, int num_args, const int &p3d_offset = 0);
   void delete_instance(P3D_instance *instance);
 
-  bool parse_token(char *arg);
-  bool parse_int_pair(char *arg, int &x, int &y);
+  bool parse_token(const char *arg);
+  bool parse_int_pair(const char *arg, int &x, int &y);
+  string lookup_token(const string &keyword) const;
+  static int compare_seq(const string &seq_a, const string &seq_b);
+  static int compare_seq_int(const char *&num_a, const char *&num_b);
   static bool is_url(const string &param);
 
   void report_downloading_package(P3D_instance *instance);