tohokuaikiのチラシの裏

技術的ネタとか。

Windowsのコマンドラインからアプリケーションのバージョンを確認する方法

CygwinPHPから使った。

レジストリにアクセスするのはPowershellに任せている。

<?php
// IE
$ie_cmd = 'reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer" /v "svcVersion"';
$r = shell_exec($ie_cmd);
$ie_version = '不明';
if (preg_match('/REG_SZ\s+(.*)/', $r, $m)){
    $ie_version = $m[1];
}
printf("IE: %s\n", $ie_version);

$csv = "";
$output_file = 'apps_output.csv';

$cmd=<<<EOF
Get-ItemProperty HKLM:Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion | export-csv  -NoTypeInformation -Encoding Default
Get-ItemProperty HKLM:Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion | export-csv  -NoTypeInformation -Encoding Default
Get-AppxPackage | Sort-Object Name | Select  PackageFullName, Version | export-csv  -NoTypeInformation -Encoding Default
Get-WmiObject -Class Win32_Product -ComputerName . | Select-Object Name, Version | Export-Csv -Encoding Default
EOF;

foreach (explode("\n", trim($cmd)) as $c){
    $c = trim($c);
    shell_exec(sprintf('powershell.exe "%s %s"', $c, $output_file));
    $csv .= "\r\n---------------------\r\n".file_get_contents($output_file);
}
file_put_contents($output_file, $csv);

$data = array();
if (($handle = fopen($output_file, "r"))) {
    while (($d = fgetcsv($handle, 1000, ","))) {
        $data[] = $d;
    }
}
// この$dataを調べると良い感じで。

Adobe Flash Professional CS3を久しぶりに使おうとしてインストールしたら意外と面倒だった件

久しぶりというか、多分最後

になるじゃないかなーって思うんだけど、6年くらい前に作ったFlashHTML5にしようと思って、素材を抜き出すために再インストールした。

インストール→Windows10再起動→Flash起動のアクティベーション…ができない。

電話認証もダメ。お客様のお使いの電話番号は現在…

あれー、CS2のアクティベーションサーバーが死んだのは知ってるけど…と思ったらCS3以降ももうだめだったのな。
helpx.adobe.com

ということで、アンインストールして…

こちらの記事に従って、再度インストール helpx.adobe.com

新しいシリアルを発行して、それが有効になるようなインストーラーをくれるみたい。

はー。アクティベーションサーバーの維持の方が大変とは…

JIRAの作業履歴を日別に出す方法(自前JavaScriptで)

フツーはtempoプラグインを使えって話なんですが…まぁ。

対象になるページ

http://jira.example.jp/projects/PRJECTID/issues/
のページをChromeFirefoxなんかで開く。

ここ。
f:id:tohokuaiki:20190402172906p:plain

このConsoleから下記のJavaScriptを入力する。

(function($){
    var output = "";
    var doList = function() {
        var ret = "";
        $('.issuePanelWrapper').find('.actionContainer').each(function(i, ac){
            var job = '', times = '';
            var date = $(ac).find('span.date').text().substring(0, 10);
            $(ac).find('ul.item-details').each(function(i, ul){
                times = $.trim($(ul).find('.worklog-duration').text());
                job   = $.trim($(ul).find('.worklog-comment').text());
                job = job.replace(/[\r\n]/g, "");
            });
            ret += date + "\t" + times + "\t" + job + "\n";
        });
        return ret;
    }
    
    var issues = $('.search-results a.splitview-issue-link');
    var i = -1;
    var timer = setInterval(function(){
        if (i >= 0){
            $(issues.get(i)).each(function(i, a){
                output += $.trim($('h1#summary-val').text()) + "\n";
            });
            output += doList();
        }
        i++;
        $(issues.get(i)).trigger('click');
        if (i >= issues.length){
            clearInterval(timer);
            console.log(output); 
        }
    }, 3000);
})(jQuery)

何となく、サーバーのレスポンスが速ければIntervalの3000を1000とかにしたりして。

WordPressの編集画面がメチャ重くなったのでメタ情報のキャッシュを作って回避

調べてみると、カスタムフィールドの定義を取得するSQLで20秒も掛かってた。

カスタムフィールド使いまくってて、20万行越えてた。
過去のデータ中から、編集画面でプルダウンを作るんだけどそれはちょっと時間かかるよね…

ということで、テーマのfuncitons.phpに以下を追加。テーマディレクトリに tmpディレクトリを作ってパーミション777に。

<?php
class AnonymousTekitou
{
    /* ローカルキャッシュの時刻 */
    private $cache_lifetime  = 8000;
    
    /* ローカルキャッシュのディレクトリレベル */
    private $cache_dir_level = 2;
    

    /**
     * @brief 
     * @param 
     * @retval
     */
    public static function getInstance($cache_lifetime = null)
    {
        static $ins ;
        
        if (is_null($ins)){
            $ins = new self();
            if (!is_null($cache_lifetime)){
                $ins->cache_lifetime = $cache_lifetime;
            }
        }
        return $ins;
    }
    
    /**
     * @brief ファイルキャッシュ
     * @param 
     * @param 保存する場合は必要
     * @retval
     */
    private function cache($url, $body = null)
    {
        $cache_file = sprintf('%s/tmp/cache/%s',
                              __DIR__, $this->splitString(md5($url), $this->cache_dir_level));
        $cache_dir  = dirname($cache_file);
        if (!is_dir($cache_dir)){
            self::mkdir($cache_dir, 0777);
        }
        chmod($cache_dir, 0777);
        
        if (is_null($body)){
            if (file_exists($cache_file)){
                $s = stat($cache_file);
                if ($s['mtime'] + $this->cache_lifetime > time()){
                    $file = file($cache_file);
                    array_shift($file);
                    return implode("", $file); // キャッシュ有効・ファイルが存在してライフタイム内
                }
                else {
                    unlink($cache_file); // キャッシュ無効・再度取得
                    return null ;
                }
            }
            return false; 
        }
        else {
            file_put_contents($cache_file, $url."\n".$body);
            chmod($cache_file, 0666);
        }
    }

    

    /**
     * @brief 文字スラッシュを入れる。ex: abcdefg => a/b/c/defg
     * @param 文字列
     * @param 分割個数
     * @retval
     */
    private function splitString($str, $num) 
    {
        $ret = "";
        for ($i=0; $i< strlen($str) ;$i++){
            $ret .= $str{$i};
            if ($i<$num){
                $ret.= "/"; 
            }
        }
        return $ret;
    }
    
    
    /**
     *  mkdir -p
     *
     *  @access public
     *  @param  string  $dir    作成するディレクトリ
     *  @param  int     $mode   パーミッション
     *  @return bool    true:成功 false:失敗
     *  @static
     */
    public static function mkdir($dir, $mode)
    {
        if (file_exists($dir)) {
            return is_dir($dir);
        }

        $parent = dirname($dir);
        if ($dir === $parent) {
            return true;
        }

        if (is_dir($parent) === false) {
            if (self::mkdir($parent, $mode) === false) {
                return false;
            }
        }

        return mkdir($dir, $mode) && chmod($dir, $mode);
    }
    
    
    
    
    /**
     * @brief postmeta_form_keysのキャッシュを作成する
     * @param $WP_Post
     * @retval
     */
    public function getPostmetaFormKeysCache($post) 
    {
        global $wpdb;

        $key_name = md5(__CLASS__ . __METHOD__ . DB_NAME . __FILE__ . $_SERVER['SERVER_NAME']);

        // postがnullの時だけキャッシュを使う
        if (!is_null($post)) {
            return null;
        }

        if ($cache = $this->cache($key_name)){
            $keys = unserialize($cache);
        }
        else {
            // make cache
            $limit = apply_filters( 'postmeta_form_limit', 30 );
            $sql = "SELECT DISTINCT meta_key
          FROM $wpdb->postmeta
          WHERE meta_key NOT BETWEEN '_' AND '_z'
          HAVING meta_key NOT LIKE %s
          ORDER BY meta_key
          LIMIT %d";
            $keys = $wpdb->get_col( $wpdb->prepare( $sql, $wpdb->esc_like( '_' ) . '%', $limit ) );
            $this->cache($key_name, serialize($keys));
        }
        
        return $keys;
    }
}

add_filter('postmeta_form_keys', function($p){
    $a= AnonymousTekitou::getInstance();
    return $a->getPostmetaFormKeysCache($p);
});

Let's Encryptのための穴あけ

Let's Encryptを使うには、httpでの接続も残しておかないと更新してくれない。.well-knownにアクセスできなくて失敗する。

httpを立てておいて、httpsにリダイレクト、でその先はBasic認証アリだとか作ってるとダメ。http => https(Basic認証アリ)

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: example.com
   Type:   unauthorized
   Detail: Invalid response from
   http://example.com/.well-known/acme-challenge/OjG***************************************3I:
   "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML
   2.0//EN\">\n<html><head>\n<title>401
   Unauthorized</title>\n</head><body>\n<h1>Unauthorized</"

で、こうやっておく。

httpアクセス側のhttpd.conf

<VirtualHost *:80>
        ServerAdmin webmaster@example.jp
        ServerName example.com
        DocumentRoot /web/example.com/htdocs

        <Directory /web/example.com/htdocs>
            RewriteEngine On
            RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
        </Directory>

        <Directory /web/example.com/htdocs/.well-known>
            RewriteEngine Off
            Require all granted
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/example.com.error.log
        CustomLog ${APACHE_LOG_DIR}/example.com.access.log combined

</VirtualHost>

.well-knowは転送無しにして、かつ Require all granted 。これが無いとあの忌々しい

[authz_core:error] [pid 2510] [client 192.168.111.111:50355] AH01630: client denied by server configuration:

が出る。