You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CFGFileParser.cpp 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // ©2008-2017 despair <despair@netrunner.cc>
  2. #include "CFGFileParser.h"
  3. #include <climits>
  4. #include "slre.h"
  5. CFGFileParser::CFGFileParser(const char* filename){
  6. // Open the config file, get its size,
  7. // allocate the buffer, read it into
  8. // the buffer, close the file
  9. cfg_file = fopen(filename, "rb"); // On NT, opening in text mode translates \n into \r\n
  10. stat(filename, cfg_fileinfo);
  11. buffer = static_cast<char*>(tlsf_malloc(cfg_fileinfo->st_size & INT_MAX));
  12. cfg = new BrowserConfiguration();
  13. bytesRead = fread(buffer, sizeof(char) & INT_MAX, cfg_fileinfo->st_size & INT_MAX, cfg_file);
  14. if (!bytesRead) {
  15. std::cout << "no config" << std::endl;
  16. }
  17. fclose(cfg_file);
  18. }
  19. CFGFileParser::~CFGFileParser(){
  20. // clean up!
  21. // This buffer has been written to and co-opted by
  22. // libc itself, but it stands that we initially allocated
  23. // it. So we'll free it ourselves.
  24. tlsf_free(buffer);
  25. // We've already copied the collected config directives
  26. // into a global class, we can safely delete the scratch
  27. // object, and its file info block.
  28. tlsf_free(cfg_fileinfo);
  29. delete cfg;
  30. }
  31. bool CFGFileParser::ParseText() {
  32. // Initial buffer for pass 1. tmp holds the config file (fmr. buffer)
  33. // token holds the actual token. pass1_length to keep track of memory,
  34. // reallocate as needed.
  35. char *tmp, *token;
  36. size_t pass1_length = 0;
  37. struct slre regex; // final validation before adding to second-pass buffer
  38. // Second pass. All comments and .tags stripped out. Starts off at 512 bytes, increases if necessary.
  39. char* directives = static_cast<char*>(tlsf_malloc(512));
  40. char* tmp2;
  41. token = strtok_r(buffer, "\n", &tmp);
  42. while (tmp != nullptr) {
  43. if (token[0] == '#' || token[0] == '.' || token[0] == '\n'){ // Comment, Perl directive, or single <LF> found, skip over
  44. token = strtok_r(nullptr, "\n", &tmp);
  45. }
  46. else if (!isalpha(token[0])){ // The leading character is NOT a #, ., <LF>, or a letter. NB: Leading numbers are also invalid.
  47. printf("ERROR: Config file is invalid\n");
  48. printf("%s\n",token);
  49. return false;
  50. }
  51. else {
  52. if (!slre_compile(&regex, "([A-Z0-9_]*)(:)(\\[.*\\])")){
  53. printf("Internal error.\n");
  54. return false;
  55. }
  56. if (!slre_match(&regex, token, strlen(token), nullptr)){
  57. printf("Invalid directive: %s\n", token); // regex matches DIREC[_]T[I1]VE:[token] but NOT directive:[token] - the directive MUST be all caps
  58. return false;
  59. }
  60. // Config directive found, add to second-pass buffer
  61. // once we reach the 0.5KB mark, realloc exactly enough to keep going
  62. if (pass1_length >= 512){
  63. tlsf_realloc(directives, pass1_length+strlen(token)+2);
  64. }
  65. strcat(directives, token);
  66. strcat(directives, "\t");
  67. pass1_length = strlen(directives);
  68. token = strtok_r(nullptr, "\n", &tmp); // continue
  69. }
  70. }
  71. // First pass complete, second pass: break up into single directives and <key, value> pairs
  72. token = strtok_r(directives, "\t", &tmp);
  73. ntr::fast_string key, value;
  74. while (tmp != nullptr){
  75. key=strtok_r(token, ":", &tmp2);
  76. value=strtok_r(nullptr, "[]", &tmp2);
  77. // strip ending bracket
  78. cfg->Settings.insert({key,value});
  79. token = strtok_r(nullptr, "\t", &tmp);
  80. }
  81. #ifdef DEBUG
  82. std::cout << "Settings stringmap contains, in no particular order:\n";
  83. for ( auto it = cfg->Settings.begin(); it != cfg->Settings.end(); ++it ){
  84. std::cout << it->first << ":" << it->second << std::endl;
  85. }
  86. std::cout << std::endl;
  87. #endif
  88. // clean up, we're done parsing
  89. tlsf_free(directives);
  90. return true;
  91. }
  92. // Writes the fully parsed configuration to a BrowserConfiguration
  93. // object supplied by the user.
  94. void CFGFileParser::WriteConfig(BrowserConfiguration &config){
  95. config.Settings = cfg->Settings;
  96. }