<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## Drupal `Drupal`中有部分代碼直接通過`file_get_contents`獲取`PHP`源碼導致加密后出現問題 ### 代碼路徑 `drupal/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php:126` ~~~php //代碼內容 protected function parse() { if ($this->parsed || !$fileName = $this->finder->findFile($this->className)) { return; } $this->parsed = true; $contents = file_get_contents($fileName); if ($this->classAnnotationOptimize) { if (preg_match("/\A.*^\s*((abstract|final)\s+)?class\s+{$this->shortClassName}\s+/sm", $contents, $matches)) { $contents = $matches[0]; } } $tokenParser = new TokenParser($contents); ...... } ~~~ 其中部分代碼如上,通過`class`名獲取文件路徑,然后通過`file_get_contents`獲取`PHP`文件的內容,其中`TokenParser`類中構造函數如下 ~~~php public function __construct($contents) { $this->tokens = token_get_all($contents); token_get_all("<?php\n/**\n *\n */"); $this->numTokens = count($this->tokens); } ~~~ 傳入獲取到的源碼通過`token_get_all`進行解析,然后后續分析代碼獲取`PHP`文件的類、屬性、方法的注釋 ,父類的命名空間 和`class`名 ,本類的`use`信息等,因為文件已經加密,所以`file_get_contents`獲取到的內容是加密后的內容,`token_get_all`就解析不到正確的信息,從而導致程序無法運行。 ### 解決方案 > 本次使用的`2.1.1`版本的加密器,通過`Swoole Compiler`加密器加密的代碼,在配置文件中`save_doc`配置選項必須設置為`1`,如果設置為`0`則不會保存注釋,并且在`2.1.3`版本`swoole_loader.so`擴展中新增加的函數`naloinwenraswwww`也無法獲取到類中use的相關信息,具體函數使用在后面會詳細說明。 ~~~php 1 $ref = new \ReflectionClass($this->className); 2 3 $parent_ref = $ref->getParentClass(); 4 5 ...... 6 7 if (is_file($fileName)) { 8 $php_file_info = unserialize(naloinwenraswwww(realpath($fileName))); 9 foreach ($php_file_info as $key => $info) { 10 if ($key == 'swoole_namespaces' || $key == 'swoole_class_name') { 11 continue; 12 } 13 $this->useStatements[$key] = $info; 14 } 15 } 16 17 $this->parentClassName = $parent_ref->getName(); 18 19 if (strpos($this->parentClassName, '\\')!==0) { 20 $this->parentClassName = '\\'.$this->parentClassName; 21 } 22 23 $static_properties = []; 24 25 $properties = $ref->getProperties(); 26 27 $parent_properties = $this->createNewArrKey($parent_ref->getProperties()); 28 29 ...... 30 31 $static_methods = []; 32 33 $methods = $ref->getMethods(); 34 35 ...... ~~~ 1. 第1行通過類名來獲取反射類`ReflectionClass`類的對象。 2. 因為此反射類包含了所有父類中的屬性和方法,但源碼中只要獲取本類中的屬性和方法,所以還要獲取父類的反射類然后通過對比來剔除父類中的屬性和方法,第3行使用`ReflectionClass`類提供的`getParentClass`方法獲取父類的反射類,此方法返回父類的`ReflectionClass`對象。 3. 第25行通過`ReflectionClass`類提供的`getProperties`方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個`ReflectionProperty`類對象。 4. 通過`ReflectionProperty`類提供的`getDocComment`方法就可以拿到屬性的注釋。 5. 同上第33行通過`ReflectionClass`類提供的`getMethods`方法可以拿到本類和父類中的方法,然后進行對比剔除父類的方法,保留本類的方法,此方法返回的是一個`ReflectionMethod`類對象。 6. 通過`ReflectionMethod`對象提供的`getDocComment`方法就可以拿到方法的注釋。 7. 通過第17行`ReflectionClass`提供的`getName`方法可以拿到類名。 > 因為反射無法獲取`use`類的信息,所以在`2.1.3`版本中的`swoole_loader.so`擴展中添加函數`naloinwenraswwww`,此函數傳入一個`PHP`文件的絕對路徑,返回傳入文件的相關信息的序列化數組,反序列化后數組如下 ~~~php [ "swoole_namespaces" => "Drupal\Core\Datetime\Element", "swoole_class_name" => "Drupal\Core\Datetime\Element\DateElementBase", "nestedarray" => "Drupal\Component\Utility\NestedArray", "drupaldatetime" => "Drupal\Core\Datetime\DrupalDateTime", "formelement"=> "Drupal\Core\Render\Element\FormElement" ] ~~~ 其中`swoole_namespaces`為文件的命名空間,`swoole_class_name`為文件的命名空間加類名,其他為`use`信息,鍵為`use`類的類名小寫字母,如存在別名則為別名的小寫字母,值為`use`類的命名空間加類名,通過該函數和反射函數可以兼容`StaticReflectionParser`中加密后出現的無法獲取正確信息的問題 ## 在加密后的未影響`Drupal`運行的潛在問題: * 代碼路徑:`drupal/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php:39` * 代碼路徑:`drupal/vendor/symfony/class-loader/ClassMapGenerator.php:91` * 代碼路徑:`drupal/vendor/symfony/routing/Loader/AnnotationFileLoader.php:90` > `Drupal`中引入了`Symfony`框架,此框架中部分代碼也是通過`file_get_contents`和`token_get_all`來獲取`PHP`文件的類名,但目前未對`Druapl`運行產生影響,可能并未用到其中方法 ### 解決方案: 同`StaticReflectionParser`類的解決方案一樣通過`2.1.3`版本中的`swoole_loader.so`擴展中添加函數`naloinwenraswwww`來獲取加密后文件的命名空間和類名 ## 尚未有更好方案的問題: * 代碼路徑:`drupal/core/includes/install.inc:220` ~~~php function drupal_rewrite_settings($settings = [], $settings_file = NULL) { if (!isset($settings_file)) { $settings_file = \Drupal::service('site.path') . '/settings.php'; } // Build list of setting names and insert the values into the global namespace. $variable_names = []; $settings_settings = []; foreach ($settings as $setting => $data) { if ($setting != 'settings') { _drupal_rewrite_settings_global($GLOBALS[$setting], $data); } else { _drupal_rewrite_settings_global($settings_settings, $data); } $variable_names['$' . $setting] = $setting; } $contents = file_get_contents($settings_file); if ($contents !== FALSE) { // Initialize the contents for the settings.php file if it is empty. if (trim($contents) === '') { $contents = "<?php\n"; } // Step through each token in settings.php and replace any variables that // are in the passed-in array. $buffer = ''; $state = 'default'; foreach (token_get_all($contents) as $token) { if (is_array($token)) { list($type, $value) = $token; } else { $type = -1; $value = $token; } // Do not operate on whitespace. if (!in_array($type, [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { switch ($state) { case 'default': if ($type === T_VARIABLE && isset($variable_names[$value])) { // This will be necessary to unset the dumped variable. $parent = &$settings; // This is the current index in parent. $index = $variable_names[$value]; // This will be necessary for descending into the array. $current = &$parent[$index]; $state = 'candidate_left'; } break; case 'candidate_left': if ($value == '[') { $state = 'array_index'; } if ($value == '=') { $state = 'candidate_right'; } break; case 'array_index': if (_drupal_rewrite_settings_is_array_index($type, $value)) { $index = trim($value, '\'"'); $state = 'right_bracket'; } else { // $a[foo()] or $a[$bar] or something like that. throw new Exception('invalid array index'); } break; case 'right_bracket': if ($value == ']') { if (isset($current[$index])) { // If the new settings has this index, descend into it. $parent = &$current; $current = &$parent[$index]; $state = 'candidate_left'; } else { // Otherwise, jump back to the default state. $state = 'wait_for_semicolon'; } } else { // $a[1 + 2]. throw new Exception('] expected'); } break; case 'candidate_right': if (_drupal_rewrite_settings_is_simple($type, $value)) { $value = _drupal_rewrite_settings_dump_one($current); // Unsetting $current would not affect $settings at all. unset($parent[$index]); // Skip the semicolon because _drupal_rewrite_settings_dump_one() added one. $state = 'semicolon_skip'; } else { $state = 'wait_for_semicolon'; } break; case 'wait_for_semicolon': if ($value == ';') { $state = 'default'; } break; case 'semicolon_skip': if ($value == ';') { $value = ''; $state = 'default'; } else { // If the expression was $a = 1 + 2; then we replaced 1 and // the + is unexpected. throw new Exception('Unexpected token after replacing value.'); } break; } } $buffer .= $value; } foreach ($settings as $name => $setting) { $buffer .= _drupal_rewrite_settings_dump($setting, '$' . $name); } // Write the new settings file. if (file_put_contents($settings_file, $buffer) === FALSE) { throw new Exception(t('Failed to modify %settings. Verify the file permissions.', ['%settings' => $settings_file])); } else { // In case any $settings variables were written, import them into the // Settings singleton. if (!empty($settings_settings)) { $old_settings = Settings::getAll(); new Settings($settings_settings + $old_settings); } // The existing settings.php file might have been included already. In // case an opcode cache is enabled, the rewritten contents of the file // will not be reflected in this process. Ensure to invalidate the file // in case an opcode cache is enabled. OpCodeCache::invalidate(DRUPAL_ROOT . '/' . $settings_file); } } else { throw new Exception(t('Failed to open %settings. Verify the file permissions.', ['%settings' => $settings_file])); } } ~~~ `Drupal`安裝過程中有個配置文件`default.setting.php`,里面存放了默認配置數組,在安裝的過程中會讓用戶在安裝界面輸入一些配置比如`Mysql`的信息,輸入過后此方法通過`file_get_contents`和`token_get_all`來獲取`setting`中的信息,然后合并用戶在頁面輸入的信息,重新存回文件,因為整個過程涉及到讀取文件,更改文件信息,在存入文件,所以`Swoole Compiler`在此處暫時沒有更好的解決方案,需要在加密的時候選擇不加密`setting`文件。 代碼路徑:`drupal/vendor/symfony/class-loader/ClassCollectionLoader.php:126` 此類中是`Symfony`讀取PHP文件然后作相應處理后緩存到文件中,存在和上面代碼同樣的問題,暫未找到更好的解決方案,建議相關文件不要加密
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看