2019年7月23日火曜日

HTML imgタグに指定したスクリプトへの値の受け渡し

2019 Jul. 23.

HTMLのimgタグに指定したスクリプトへの値の受け渡しはGETリクエスト。
書式: <img src='SCRIPT.php?var1=VALUE1&var2=VALUE2'>
 値は文字列でも引用符で囲まない。
PHPでの受け取りは $_GET['var1'] に VALUE1 が入る。

[呼び出し元]
<?php
$phpFilePath = "/myProject/my_php/display_jpg.php?imgFile=myImage.jpg";
echo "<img src='{$phpFilePath}'>";
?>

[呼ばれる側](/myProject/my_php/display_jpg.php)
<?php
$jpgpath = "/virtual/rokkonet/public_html/www.rokkonet.ga/dispose_list/data/{$_GET['imgFile']}";
?>

XREA WordPress imgタグからphpスクリプトを読み込んで画像を表示する img src="SCRIPT.php"

2019 Jul. 23.

テキストとして読み込まれたHTMLファイルの途中で header("Content-Type: image/jpeg") を発行しても有効にならない。
"Content-Type: image/jpeg" を指定してimgタグに直接画像を指定しても、画像はテキスト扱いされ文字化け表示される。
 「fopen(), fread(), fclose()」「file_get_contents()」「readfile()」「imagejpeg()」はいずれも画像表示に失敗する。
imgタグに画像を表示するphpスクリプトを指定する。

[画像を表示するページとなるfoo.phpの保存場所]

/public_html/www.MyXrea.Domain/myProject/my_php/foo.php



[foo.php内の画像表示部]

// imgタグに指定するphpファイルのパス指定は /myProject から始まる
$phpFilePath = "/myProject/my_php/display_jpg.php";
echo "<img src='{$phpFilePath}'>";


[foo.phpから呼び出されるdisplay_jpg.phpの保存場所] 

/public_html/www.MyXrea.Domain/myProject/my_php/display_jpg.php

[画像ファイルの保存場所]

 /virtual/XREA-NAME/public_html/www.MyXrea.Domain/myProject/data/myImage.jpg

[display_jpg.phpの画像表示部]

<?php
header("Content-Type: image/jpeg");
$jpgpath = "/virtual/XREA-NAME/public_html/www.MyXrea.Domain/myProject/data/myImage.jpg";
  // 画像ファイルパスは /virtual/XREA-NAME/public_html/www.MyXrea.Domain から始める
$img = imagecreatefromjpeg( $jpgpath );
imagejpeg( $img );
imagedestroy( $img );
?>

2019年7月15日月曜日

android AsyncTaskによるJSchを用いたSSH通信とAsyncTask内イベントの呼び出し元クラスでのキャッチ

2019 Jul. 15.

MyJsch.java
package your.package;

import android.content.Context;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;

import java.io.File;
import java.io.InputStream;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;

class MyJsch {
    private final String ServerIp;
    private final int Port;
    private final String User;
    private final String PassPhraseWord;
    private final String IdentityKeyPath;
    private final Context AppContext;

    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";

    /*
     * コンストラクタ
     */
    MyJsch( final String ServerIp, final int Port, final String User, final String PassPhraseWord,
            final String IdentityKeyPath, final Context AppContext) {
        this.ServerIp = ServerIp;
        this.Port = Port;
        this.User = User;
        this.PassPhraseWord = PassPhraseWord;
        this.IdentityKeyPath = IdentityKeyPath;
        this.AppContext = AppContext;
    }


    /*
     * Sessionを開始
     */
    protected Session connectSession() throws JSchException {
        Session session = null;

        // android端末内の外部ストーリッジ確認
        List sdCardFilesDirPaths =
                SdCardDirPaths.getSdCardFilesDirPathListForLollipop( AppContext );
        Collections.sort(sdCardFilesDirPaths, new CompStringLength());
        String externalPath = sdCardFilesDirPaths.get(0);
        externalPath = externalPath.replaceAll("/Android.*$", "");

        final JSch jsch = new JSch();

        // クライアント側のknownHostsチェックを行わない
        Hashtable config = new Hashtable();
        config.put("StrictHostKeyChecking", "no");
        jsch.setConfig(config);

        // パスフレーズ・秘密鍵方式
        String privKeyFilePath = externalPath + "/" + IdentityKeyPath;
        File privKeyFile = new File(privKeyFilePath);
        if (privKeyFile.exists() ) {
            jsch.addIdentity(privKeyFilePath, PassPhraseWord);
        }

        // Session取得
        session = jsch.getSession(User, ServerIp, Port);

        // パスワード方式でも可とする
        session.setPassword(PassPhraseWord);

        final UserInfo userInfo = new SftpUserInfo();
        session.setUserInfo(userInfo);
        session.connect();
        return session;
    }


    /**
     * SFTPのChannelを開始
     *
     * @param session
     *            開始されたSession情報
     */
    protected ChannelSftp connectChannelSftp(final Session session)
            throws JSchException {
        final ChannelSftp channel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
        try {
            channel.connect();
        } catch (JSchException e) {
            return null;
        }
        return channel;
    }


    /**
     * Session・Channelの終了
     *
     * @param session
     *            開始されたSession情報
     * @param channels
     *            開始されたChannel情報.複数指定可能
     */
    protected void disconnect(final Session session, final Channel... channels) {
        if (channels != null) {
            for (Channel c: channels ) {
                if (c != null) {
                    c.disconnect();
                }
            }
        }
        if (session != null) {
            session.disconnect();
        }
    }


    /**
     * SFTPに接続するユーザ情報を保持するクラス
     */
    private static class SftpUserInfo implements UserInfo {
        @Override
        public String getPassword() {
            return null;
        }
        @Override
        public boolean promptPassword(String arg0) {
            return true;
        }
        @Override
        public boolean promptPassphrase(String arg0) {
            return true;
        }
        @Override
        public boolean promptYesNo(String arg0) {
            return true;
        }
        @Override
        public void showMessage(String arg0) {
        }
        @Override
        public String getPassphrase() {
            return null;
        }
    }


    /**
     * ファイルアップロード
     *
     * @throws JSchException
     *             Session・Channelの設定/接続エラー時に発生
     */
    public void putFile(ChannelSftp channel, InputStream inStream, String destPath)
            throws SftpException {

        /*
         * sftp通信を実行
         */
        String absoluteDestPath = channel.getHome() + "/" + destPath;
        String destFile = new File(absoluteDestPath).getName();
        int numDestPath = absoluteDestPath.length();
        int numDestFile = destFile.length();
        String destParentPath = absoluteDestPath.substring( 0, numDestPath - numDestFile );
        channel.cd(destParentPath);
        channel.put( inStream, destFile);

        // confirm existance of destFile
        channel.lstat(destFile);
    }

    /*
     * サーバー上のファイルの削除
     *   destFileNameFront文字列から始まるファイルを全て削除する
    */
    public void deleteFiles(ChannelSftp channel, String destFileNameFront) throws SftpException {
        channel.rm(destFileNameFront + "*");
    }
}

SdCardDirPaths.java
package your.package;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class SdCardDirPaths {

    /**
     * SDカードのfilesディレクトリパスのリストを取得する。
     * Android5.0以上対応。
     *
     * @param context
     * @return SDカードのfilesディレクトリパスのリスト
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static List getSdCardFilesDirPathListForLollipop(Context context) {
        List sdCardFilesDirPathList = new ArrayList<>();

        // getExternalFilesDirsはAndroid4.4から利用できるAPI。
        // filesディレクトリのリストを取得できる。
        File[] dirArr = context.getExternalFilesDirs(null);


        for (File dir : dirArr) {
            if (dir != null) {
                String path = dir.getAbsolutePath();

                // isExternalStorageRemovableはAndroid5.0から利用できるAPI。
                // 取り外し可能かどうか(SDカードかどうか)を判定している。
                if (Environment.isExternalStorageRemovable(dir)) {

                    // 取り外し可能であればSDカード。
                    // このパスをパスリストに加える
                    if (!sdCardFilesDirPathList.contains(path)) {
                        sdCardFilesDirPathList.add(path);
                    }
                }
            }
        }
        return sdCardFilesDirPathList;
    }
}

(利用例)
Send2ServerTask.java
package your.package;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

// 複数のファイルをSSH送信する
public class Send2ServerTask extends AsyncTask {
    final String ServerIp = "SSH.SERVER.IP.ADDRESS";
    final int Port = 22;
    final String User = "SshLogInUser";
    final String IdentityKeyPath = "PRIVATE/KEY/FILE/PATH/IN/CLIENT/DEVICE";
    //     if IdentityKeyPath is illegal, password authentication is used.
    final String DestParentPath = "SERVER/DIR/TO/BE/STORED";

    private WeakReference weakRef;
    private HashMap inStreamMap;
    final private String passPhrase;
    final private String fileNameFront;
      // SSH失敗時のファイル削除のためにファイル名共通文字列を保持
      // 複数の送信ファイルはいずれもfileNameFront文字列で始まるファイル名とすること

    private Listener listener;

    /*
     * constructor
     *   inStreamMap 送信する複数ファイルのファイル名とインプットストリームをHashMapで渡す
     */
    Send2ServerTask(Activity parentActivity, HashMap inStreamMap,
                    String passPhrase, String fileNameFront) {
        weakRef = new WeakReference<>(parentActivity);
        this.inStreamMap = new HashMap<>(inStreamMap);
        this.passPhrase = passPhrase;
        this.fileNameFront = fileNameFront;
    }


    @Override
    protected String doInBackground(Void... params) {
        MyJsch mJsch;
        Session sftpSession = null;
        ChannelSftp sftpChannel = null;

        Activity refActivity = weakRef.get();
        if (refActivity == null || refActivity.isFinishing()) {
            return null;
        }

        Context appContext = weakRef.get().getApplicationContext();

        // initialise Jsch
        mJsch = new MyJsch(ServerIp, Port, User, passPhrase, IdentityKeyPath, appContext);

        // connect session, channel
        try {
            sftpSession = mJsch.connectSession();
            sftpChannel = mJsch.connectChannelSftp( sftpSession );

            // upload
            int count = 0;
            for ( Map.Entry entry : inStreamMap.entrySet()) {
                // entry.getKey()    entry.getValue()
                String destPath = DestParentPath + "/" + entry.getKey();
                try {
                    mJsch.putFile(sftpChannel, entry.getValue(), destPath);
                } catch (SftpException e) {
                    try {
                        // このセッションでアップロードされたファイルをすべて削除する
                        mJsch.deleteFiles(sftpChannel, fileNameFront);
                        mJsch.disconnect( sftpSession, sftpChannel);
                        return "Failed to upload files. count: " + count + ". " + destPath + " "  + e.toString();
                    } catch (SftpException e1) {
                        mJsch.disconnect( sftpSession, sftpChannel);
                        return "Failed to delete remote files. " + e1.toString();
                    }
                }

                try {
                    // take sleep between SFTP#puts
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // このセッションでアップロードされたファイルをすべて削除する
                    mJsch.deleteFiles(sftpChannel, fileNameFront);
                    mJsch.disconnect( sftpSession, sftpChannel);
                    return "Failed! sleep" + e.toString();
                }
                count++;
            }
            if ( count != inStreamMap.size()) {
                // このセッションでアップロードされたファイルをすべて削除する
                mJsch.deleteFiles(sftpChannel, fileNameFront);
                mJsch.disconnect( sftpSession, sftpChannel);
                return "Could not upload " + inStreamMap.size() + " files";
            }
        } catch (JSchException | SftpException e) {
            mJsch.disconnect( sftpSession, sftpChannel);
            return "connection failed. " + e.toString();

        } finally {
            // disconnect channel, session
            mJsch.disconnect( sftpSession, sftpChannel);
        }
        return "Succeeded. " + inStreamMap.size() + " files upload";
    }


    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        Activity refActivity = weakRef.get();
        if (refActivity == null || listener == null)  {
            Toast.makeText(refActivity, "failed sending to server.", Toast.LENGTH_LONG).show();
        } else {
            if ( result.contains("Succeeded") ) {
                Toast.makeText(refActivity, result, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(refActivity, result, Toast.LENGTH_LONG).show();
            }
            listener.onSuccess(result);
        }
        return;
    }

    void setListener(Listener listener) {
        this.listener = listener;
    }

    interface Listener {
        void onSuccess(String str);
    }
}

MyActivity.java
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_confirm_before_send);
        buttonOK = findViewById(R.id.buttonOK);
        setListeners();
    }

    /*
     * Send2ServerTaskへのリスナ
     *   サーバーへのアップロード終了後に行う処理を記述
     */
    private Send2ServerTask.Listener createListener() {
        return new Send2ServerTask.Listener() {
            @Override
            public void onSuccess(String result) {
                deleteFiles();
            }
        };
    }

    protected void setListeners(){
        buttonOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*
                 * HashMap SSHサーバーに送るデータ
                 *   String 送信先ファイルパス
                 *   InputStream 送信ファイルのインプットストリーム
                 */
                HashMap dataMap = new HashMap<>();

                setData2dataMap(); // dataMapにSSH通信データをセットする
                setPassPhraseWord();
                setFileNameFront();

                /*
                 * dataMapを保管サーバーに送る
                 */
                send2serverTask = new Send2ServerTask(thisActivity, dataMap, passPhraseWord, fileNameFront);

                // Listenerを設定し、send2serverTaskを実行してdataMapを保管サーバーに送る
                send2serverTask.setListener(createListener());
                send2serverTask.execute();
            }
        });
    }

httpサーバー リダイレクト設定

2019 Jul. 15.

https://www.jaskun.com/server/xrea-server/xrea301/ より

aaa.com を www.aaa.com にリダイレクトする例


.htaccess に次の3行を記述する
  RewriteEngine on
  RewriteCond %{HTTP_HOST} ^aaa\.com
  RewriteRule ^(.*)$ http://www.aaa.com/$1 [R=301,L]

xrea SSH通信許可設定

2019 Jul. 15.

  1. xreaにログイン
  2. 旧コントロールパネルを表示
  3. 管理メニュー -> ホスト情報登録
  4. 「SSH登録」をクリック

2019年7月13日土曜日

xreaサイトのSSL化

2019 Jul. 13.

参考元

https://damema.net/article/17/
https://www.hobofoto.net/xrea-ssl/

  1. xreaのサイト設定変更で「無料SSL」設定する
  2. xrea画面右上のプルダウンメニューから「旧コンパネ切替」する
  3. マイドメイン利用->ドメインウェブ->SSL設定 で「SSLを有効にするドメイン名」にSSL設定するドメインを選択し、「証明書設定」をクリックする
  4. 4つの大きな窓が内、下部の3つが埋まるまで、キャンセルと前記「証明書設定」クリックを繰り返す。あるいは、参考元サイトに書かれているように、コピー&ペーストする。
    3つの窓が埋まると、下部の「インストール」をクリックする。
    (必要3データ )
     プライベートキー[パスフレーズなし]SSLCertificateKeyFile
     発行された証明書(必須) SSLCertificateFile
     発行された中間証明書(必須) SSLCACertificateFile
  5.  マイドメイン利用->ドメインウェブ画面の下部の「ドメイン設定」をクリックする

xreaに独自ドメイン設定

2019 Jul. 13.


参考元 https://www.homepage-tukurikata.com/domain/coreserver-dns.html
  1. freenomで独自ドメイン取得
  2. freenomで"Manage Domain" ->  "Manage Freenom DNS" -> "Add Records"に進みNameにホスト名(wwwにした)、TTLに3600、TargetにxreaのサーバーIPアドレスを指定
  3. バリュードメインサイトの「無料ネームサーバー」->「他社登録しているドメインを登録」でfreenomで取得したドメインを登録
  4. バリュードメインの「無料ネームサーバー」->「ドメインのDNS設定」で「当サービス内サーバーの自動DNS設定」からxreaで取得したサーバーのドメインを選択
  5. xreaの「ドメイン設定」->「ドメイン設定の新規作成」で "ホスト名.freecomで取得のドメイン" を設定


2019年7月8日月曜日

NHKらじるらじるの録音

2019 Jul. 08.

らじるらじるの配信形式


  • HLS(HTTP Live Streaming) HE-AAC形式
  • M3Uプレイリストフォーマット
  • 各チャンネルのURLはconfig_web.xmlファイルに記載




 録画コマンド

$ ffmpeg -i ChannelAspxUrl -t SECONDS -codec copy OUTFILE.m4a

2019年7月6日土曜日

radikoの音声コーデックは48kbps HE-AAC v2 ステレオ

2019 Jul. 06.

radikoの音声コーデックは「48kbps HE-AAC v2 ステレオ」。
「MPEG-4 AAC Plus SBR」「aacPlus v2」「eAAC+」とも言われる。