29 #include "prc_parameters.h" 34 #ifdef PRC_PUBLIC_KEYS_INCLUDE 35 #include PRC_PUBLIC_KEYS_INCLUDE 57 _loaded_implicit =
false;
58 _currently_loading =
false;
61 #ifdef PRC_PUBLIC_KEYS_INCLUDE 63 PrcKeyRegistry::get_global_ptr()->record_keys(prc_pubkeys, num_prc_pubkeys);
64 #endif // PRC_PUBLIC_KEYS_INCLUDE 72 ~ConfigPageManager() {
74 <<
"Internal error--ConfigPageManager destructor called!\n";
86 if (_currently_loading) {
91 _currently_loading =
true;
95 for (pi = _implicit_pages.begin(); pi != _implicit_pages.end(); ++pi) {
98 _implicit_pages.clear();
103 uint64_t blob_offset;
106 uint16_t num_pointers;
110 const void *module_table;
111 const char *prc_data;
112 const char *default_prc_dir;
113 const char *prc_dir_envvars;
114 const char *prc_path_envvars;
115 const char *prc_patterns;
116 const char *prc_encrypted_patterns;
117 const char *prc_encryption_key;
118 const char *prc_executable_patterns;
119 const char *prc_executable_args_envvar;
120 const char *main_dir;
121 const char *log_filename;
124 const BlobInfo *blobinfo = (
const BlobInfo *)GetProcAddress(GetModuleHandle(NULL),
"blobinfo");
125 #elif defined(RTLD_MAIN_ONLY) 126 const BlobInfo *blobinfo = (
const BlobInfo *)dlsym(RTLD_MAIN_ONLY,
"blobinfo");
130 const BlobInfo *blobinfo = (
const BlobInfo *)dlsym(dlopen(NULL, RTLD_NOW),
"blobinfo");
132 if (blobinfo ==
nullptr) {
137 }
else if (blobinfo->version == 0 || blobinfo->num_pointers < 10) {
141 if (blobinfo !=
nullptr) {
142 if (blobinfo->num_pointers >= 11 && blobinfo->main_dir !=
nullptr) {
153 _prc_patterns.clear();
155 string prc_patterns = PRC_PATTERNS;
156 if (blobinfo !=
nullptr && blobinfo->prc_patterns !=
nullptr) {
157 prc_patterns = blobinfo->prc_patterns;
159 if (!prc_patterns.empty()) {
160 vector_string pat_list;
162 _prc_patterns.reserve(pat_list.size());
163 for (
size_t i = 0; i < pat_list.size(); ++i) {
170 _prc_patterns.push_back(glob);
175 _prc_encrypted_patterns.clear();
177 string prc_encrypted_patterns = PRC_ENCRYPTED_PATTERNS;
178 if (blobinfo !=
nullptr && blobinfo->prc_encrypted_patterns !=
nullptr) {
179 prc_encrypted_patterns = blobinfo->prc_encrypted_patterns;
181 if (!prc_encrypted_patterns.empty()) {
182 vector_string pat_list;
184 _prc_encrypted_patterns.reserve(pat_list.size());
185 for (
size_t i = 0; i < pat_list.size(); ++i) {
190 _prc_encrypted_patterns.push_back(glob);
195 _prc_executable_patterns.clear();
197 string prc_executable_patterns = PRC_EXECUTABLE_PATTERNS;
198 if (blobinfo !=
nullptr && blobinfo->prc_executable_patterns !=
nullptr) {
199 prc_executable_patterns = blobinfo->prc_executable_patterns;
201 if (!prc_executable_patterns.empty()) {
202 vector_string pat_list;
204 _prc_executable_patterns.reserve(pat_list.size());
205 for (
size_t i = 0; i < pat_list.size(); ++i) {
210 _prc_executable_patterns.push_back(glob);
215 _search_path.
clear();
220 string prc_dir_envvars = PRC_DIR_ENVVARS;
221 if (blobinfo !=
nullptr && blobinfo->prc_dir_envvars !=
nullptr) {
222 prc_dir_envvars = blobinfo->prc_dir_envvars;
224 if (!prc_dir_envvars.empty()) {
225 vector_string prc_dir_envvar_list;
227 for (
size_t i = 0; i < prc_dir_envvar_list.size(); ++i) {
229 if (!prc_dir.empty()) {
232 if (scan_auto_prc_dir(prc_dir_filename)) {
242 string prc_path_envvars = PRC_PATH_ENVVARS;
243 if (blobinfo !=
nullptr && blobinfo->prc_path_envvars !=
nullptr) {
244 prc_path_envvars = blobinfo->prc_path_envvars;
246 if (!prc_path_envvars.empty()) {
247 vector_string prc_path_envvar_list;
249 for (
size_t i = 0; i < prc_path_envvar_list.size(); ++i) {
252 while (p < path.length()) {
253 size_t q = path.find_first_of(DEFAULT_PATHSEP, p);
254 if (q == string::npos) {
259 if (scan_auto_prc_dir(prc_dir_filename)) {
276 string prc_path2_envvars = PRC_PATH2_ENVVARS;
277 if (!prc_path2_envvars.empty() && blobinfo ==
nullptr) {
278 vector_string prc_path_envvar_list;
280 for (
size_t i = 0; i < prc_path_envvar_list.size(); ++i) {
283 while (p < path.length()) {
284 size_t q = path.find_first_of(
' ', p);
285 if (q == string::npos) {
288 Filename prc_dir_filename = path.substr(p, q - p);
289 if (scan_auto_prc_dir(prc_dir_filename)) {
300 string default_prc_dir = DEFAULT_PRC_DIR;
301 if (blobinfo !=
nullptr && blobinfo->default_prc_dir !=
nullptr) {
302 default_prc_dir = blobinfo->default_prc_dir;
304 if (!default_prc_dir.empty()) {
306 Filename prc_dir_filename = default_prc_dir;
307 if (scan_auto_prc_dir(prc_dir_filename)) {
315 ConfigFiles config_files;
319 std::set<Filename> unique_dirnames;
328 if (unique_dirnames.insert(canonical).second) {
337 vector_string::reverse_iterator fi;
338 for (fi = files.rbegin(); fi != files.rend(); ++fi) {
340 Globs::const_iterator gi;
341 for (gi = _prc_patterns.begin();
342 gi != _prc_patterns.end();
344 if ((*gi).matches(*fi)) {
345 file_flags |= FF_read;
349 for (gi = _prc_encrypted_patterns.begin();
350 gi != _prc_encrypted_patterns.end();
352 if ((*gi).matches(*fi)) {
353 file_flags |= FF_read | FF_decrypt;
357 for (gi = _prc_executable_patterns.begin();
358 gi != _prc_executable_patterns.end();
360 if ((*gi).matches(*fi)) {
361 file_flags |= FF_execute;
365 if (file_flags != 0) {
367 file._file_flags = file_flags;
368 file._filename =
Filename(directory, (*fi));
369 config_files.push_back(file);
379 if (blobinfo !=
nullptr && blobinfo->prc_data !=
nullptr) {
382 _implicit_pages.push_back(page);
383 _pages_sorted =
false;
385 std::istringstream in(blobinfo->prc_data);
393 ConfigFiles::reverse_iterator ci;
394 for (ci = config_files.rbegin(); ci != config_files.rend(); ++ci) {
395 const ConfigFile &file = (*ci);
398 if ((file._file_flags & FF_execute) != 0 &&
403 string envvar = PRC_EXECUTABLE_ARGS_ENVVAR;
404 if (blobinfo !=
nullptr && blobinfo->prc_executable_args_envvar !=
nullptr) {
405 envvar = blobinfo->prc_executable_args_envvar;
407 if (!envvar.empty()) {
418 _implicit_pages.push_back(page);
419 _pages_sorted =
false;
423 }
else if ((file._file_flags & FF_decrypt) != 0) {
430 <<
"Unable to read " << filename <<
"\n";
434 _implicit_pages.push_back(page);
435 _pages_sorted =
false;
437 if (blobinfo !=
nullptr && blobinfo->prc_encryption_key !=
nullptr) {
444 }
else if ((file._file_flags & FF_read) != 0) {
451 <<
"Unable to read " << filename <<
"\n";
455 _implicit_pages.push_back(page);
456 _pages_sorted =
false;
463 if (!_loaded_implicit) {
464 config_initialized();
465 _loaded_implicit =
true;
468 _currently_loading =
false;
471 #ifdef USE_PANDAFILESTREAM 475 (
"newline-mode", PandaFileStreamBuf::NM_native,
476 PRC_DESC(
"Controls how newlines are written by Panda applications writing " 477 "to a text file. The default, \"native\", means to write newlines " 478 "appropriate to the current platform. You may also specify \"binary\", " 479 "to avoid molesting the file data, or one of \"msdos\", \"unix\", " 481 PandaFileStreamBuf::_newline_mode = newline_mode;
482 #endif // USE_PANDAFILESTREAM 488 (
"show-dll-error-dialog",
false,
489 PRC_DESC(
"Set this true to enable the Windows system dialog that pops " 490 "up when a DLL fails to load, or false to disable it. It is " 491 "normally false, but it may be useful to set it true to debug " 492 "why a DLL is not loading. (Note that this actually disables " 493 "*all* critical error messages, and that it's a global setting " 494 "that some other libraries might un-set.)"));
495 if (show_dll_error_dialog) {
498 SetErrorMode(SEM_FAILCRITICALERRORS);
513 _explicit_pages.push_back(page);
514 _pages_sorted =
false;
529 for (pi = _explicit_pages.begin(); pi != _explicit_pages.end(); ++pi) {
531 _explicit_pages.erase(pi);
543 void ConfigPageManager::
544 output(std::ostream &out)
const {
545 out <<
"ConfigPageManager, " 546 << _explicit_pages.size() + _implicit_pages.size()
553 void ConfigPageManager::
554 write(std::ostream &out)
const {
556 out << _explicit_pages.size() <<
" explicit pages:\n";
558 Pages::const_iterator pi;
559 for (pi = _explicit_pages.begin(); pi != _explicit_pages.end(); ++pi) {
567 out <<
" (invalid signature: ";
575 out <<
"\n" << _implicit_pages.size() <<
" implicit pages:\n";
576 for (pi = _implicit_pages.begin(); pi != _implicit_pages.end(); ++pi) {
584 out <<
" (invalid signature: ";
598 if (_global_ptr ==
nullptr) {
605 class CompareConfigPages {
616 void ConfigPageManager::
618 sort(_implicit_pages.begin(), _implicit_pages.end(), CompareConfigPages());
619 sort(_explicit_pages.begin(), _explicit_pages.end(), CompareConfigPages());
621 _pages_sorted =
true;
634 bool ConfigPageManager::
635 scan_auto_prc_dir(
Filename &prc_dir)
const {
636 string prc_dir_string = prc_dir;
637 if (prc_dir_string.substr(0, 6) ==
"<auto>") {
638 Filename suffix = prc_dir_string.substr(6);
644 if (scan_up_from(prc_dir, dir, suffix)) {
650 if (scan_up_from(prc_dir, dir, suffix)) {
655 std::cerr <<
"Warning: unable to auto-locate config files in directory named by \"" 656 << prc_dir <<
"\".\n";
672 bool ConfigPageManager::
678 if (consider.is_directory()) {
679 if (consider.scan_directory(files)) {
680 vector_string::const_iterator fi;
681 for (fi = files.begin(); fi != files.end(); ++fi) {
682 Globs::const_iterator gi;
683 for (gi = _prc_patterns.begin();
684 gi != _prc_patterns.end();
686 if ((*gi).matches(*fi)) {
692 for (gi = _prc_executable_patterns.begin();
693 gi != _prc_executable_patterns.end();
695 if ((*gi).matches(*fi)) {
712 return scan_up_from(result, parent, suffix);
721 void ConfigPageManager::
722 config_initialized() {
727 (
"panda-package-version",
"local_dev",
728 PRC_DESC(
"This can be used to specify the value returned by " 729 "PandaSystem::get_package_version_str(), in development mode only, " 730 "and only if another value has not already been compiled in. This " 731 "is intended for developer convenience, to masquerade a development " 732 "build of Panda as a different runtime version. Use with caution."));
734 (
"panda-package-host-url",
"",
735 PRC_DESC(
"This can be used to specify the value returned by " 736 "PandaSystem::get_package_host_url(), in development mode only, " 737 "and only if another value has not already been compiled in. This " 738 "is intended for developer convenience, to masquerade a development " 739 "build of Panda as a different runtime version. Use with caution."));
742 panda_sys->set_package_version_string(panda_package_version);
743 panda_sys->set_package_host_url(panda_package_host_url);
748 (
"text-encoding", TextEncoder::E_utf8,
749 PRC_DESC(
"Specifies how international characters are represented in strings " 750 "of 8-byte characters presented to Panda. See TextEncoder::set_encoding()."));
754 (
"filesystem-encoding", TextEncoder::E_utf8,
755 PRC_DESC(
"Specifies the default encoding used for wide-character filenames."));
static PandaSystem * get_global_ptr()
Returns the global PandaSystem object.
std::string get_dirname() const
Returns the directory part of the filename.
get_name
Returns the name of the page.
static size_t extract_words(const std::string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
This class is used as a namespace to group several global properties of Panda.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
set_case_sensitive
Sets whether the match is case sensitive (true) or case insensitive (false).
This is a convenience class to specialize ConfigVariable as a boolean type.
void clear()
Removes all the directories from the search list.
void set_binary()
Indicates that the filename represents a binary file.
void set_text()
Indicates that the filename represents a text file.
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
bool read_encrypted_prc(std::istream &in, const std::string &password)
Automatically decrypts and reads the stream, given the indicated password.
bool is_empty() const
Returns true if the search list is empty, false otherwise.
get_signature
Returns the raw binary signature that was found in the prc file, if any.
set_default_encoding
Specifies the default encoding to be used for all subsequently created TextEncoder objects.
bool make_canonical()
Converts this filename to a canonical name by replacing the directory part with the fully-qualified d...
bool make_true_case()
On a case-insensitive operating system (e.g.
get_dtool_name
Returns the name of the libdtool DLL that is used in this program, if it can be determined.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void append_directory(const Filename &directory)
Adds a new directory to the end of the search list.
static std::ostream & out()
A convenient way to get the ostream that should be written to for a Notify- type message.
get_trust_level
Returns the trust level associated with this page.
bool read_prc(std::istream &in)
Reads the contents of a complete prc file, as returned by the indicated istream, into the current pag...
static Notify * ptr()
Returns the pointer to the global Notify object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A global object that maintains the set of ConfigPages everywhere in the world, and keeps them in sort...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void set_filesystem_encoding(TextEncoder::Encoding encoding)
Specifies the default encoding to be used for all subsequent Filenames.
get_num_directories
Returns the number of directories on the search list.
bool is_executable() const
Returns true if the filename exists and is executable.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
This is a convenience class to specialize ConfigVariable as a string type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void reload_implicit_pages()
Searches the PRC_DIR and/or PRC_PATH directories for *.prc files and loads them in as pages.
ConfigPage * make_explicit_page(const std::string &name)
Creates and returns a new, empty ConfigPage.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class specializes ConfigVariable as an enumerated type.
A page of ConfigDeclarations that may be loaded or unloaded.
bool is_directory() const
Returns true if the filename exists and is a directory name, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void config_initialized()
Intended to be called only by Config, this is a callback that indicates to Notify when Config has don...
get_directory
Returns the nth directory on the search list.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool scan_directory(vector_string &contents) const
Attempts to open the named filename as if it were a directory and looks for the non-hidden files with...
static void set_notify_ptr(std::ostream *ptr)
Sets the ostream that is used to write error messages to.
set_environment_variable
Changes the definition of the indicated environment variable.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool delete_explicit_page(ConfigPage *page)
Removes a previously-constructed ConfigPage from the set of active pages, and deletes it.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void output_brief_signature(std::ostream &out) const
Outputs the first few hex digits of the signature.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
get_environment_variable
Returns the definition of the indicated environment variable, or the empty string if the variable is ...