MW211 EXIT

devlog
C言語/連想配列的定数のようなもの
2013年05月12日
連想配列を実装していないC言語において、
連想配列的定数のような、データベースの定数テーブル的なものを代用する処理。

まず、構造体を決める。列はいくつでもOK。
┌──────────────────────────────────────┐
│typedef struct {                                                            │
│    int    id;                                                              │
│    char*  name;                                                            │
│} DEF;                                                                      │
└──────────────────────────────────────┘

次に値を設定する。グローバル変数(配列)として先頭で定義してしまう感じか。
┌──────────────────────────────────────┐
│DEF gDef[] = {                                                              │
│    { 1,"北海道"},                                                          │
│    { 2,"青森県"},                                                          │
│    { 3,"岩手県"},                                                          │
│};                                                                          │
└──────────────────────────────────────┘

これを「id」指定で取得する関数をつくる。
┌──────────────────────────────────────┐
│DEF*  getDef(int  id) {                                                     │
│    for (int i = 0; i < (sizeof(gDef) / sizeof(gDef[0])); i++) {            │
│        if (gDef[i].id == id) {                                             │
│            return &gDef[i];                                                │
│        }                                                                   │
│    }                                                                       │
│    // 該当なしはNULLを返す                                                 │
│    return NULL;                                                            │
│}                                                                           │
└──────────────────────────────────────┘

ま、こんな感じで必要に応じて、関数をアレンジしつつ実装していくことになる。
switch-case文の雨あられよりは大分ましになるだろう。
分類:C/C++
Apache/Basic認証
2013年05月11日
Basic認証を設定したディレクトリはログインダイアログで
ログインID(ユーザ名など)とパスワードを入力して照合されないと
そのファイルにアクセスできなくなる。

ログインダイアログとか定型のものが使えるので便利かも。

実態としては、Apacheの設定にて、特定ディレクトリのアクセスを拒否した上で
Basic認証で特別に許可にしてあげますよといった感じ。

以下に設定ファイル「.htaccess」を使った場合を記述する。

設定ファイル「.htaccess」を対象とするディレクトリ直下に置く。

設定ファイル「.htaccess」の内容
┌──────────────────────────────────────┐
│<Files ~ "^\.(htaccess|htpasswd)$">                                         │
│    deny from all               ←ログイン関係のファイル以外全てアクセス拒否│
│</Files>                                                                    │
│                                                                            │
│Order deny,allow                      ←基本「拒否」、でも例外的「許可」あり│
│AuthType Basic                        ←Basic認証ですよ                     │
│AuthUserFile C:/www/.htpasswd         ←パスワードファイルのファイルパス    │
│AuthName "Password Area"              ←ログインダイアログに表示される      │
│Require valid-user                                                          │
└──────────────────────────────────────┘

設定ファイル「.htaccess」で指定したパスワードファイルの場所に
パスワードファイルを置く(指定と一致すればよく、ファイル名は任意)。
#なお、相対パスにすると、Apacheの実行ファイルからの相対パスと
  なってしまうようなので、絶対パスの指定となる。

パスワードファイル(.htpasswd)の内容
┌──────────────────────────────────────┐
│user:pass                                    ←「ユーザID:パスワード」の形式│
└──────────────────────────────────────┘
とりあえずは平文のケースは上記の通り。

ある程度暗号化(符号化?)してセキュリティを高めることはできるようだが
それについてはおいおい。
分類:Apache
Apache/ディレクトリへのアクセス
2013年05月10日
特定の相手のみアクセスを許可したい場合(残りは全てアクセス拒否)。
┌──────────────────────────────────────┐
│<Directory ディレクトリ>                                                    │
│    Order deny,allow                                                        │
│    Deny from all                                                           │
│    Allow from 特定の相手                                                   │
│</Directory>                                                                │
└──────────────────────────────────────┘
「Order」は処理順をあらわし、全てをアクセス拒否してから、
特定の相手のみ許可することになる。
よって、優先順とは逆になる。
(後の方が上書となるので結果的に優先順が高くなる)

特定の相手のみアクセスを拒否したい場合(残りは全てアクセス許可)。
┌──────────────────────────────────────┐
│<Directory ディレクトリ>                                                    │
│    Order allow,deny                                                        │
│    Allow from all                                                          │
│    Deny from 特定の相手                                                    │
│</Directory>                                                                │
└──────────────────────────────────────┘
「Order」は処理順をあらわし、全てをアクセス許可してから、
特定の相手のみ拒否することになる。
よって、優先順とは逆になる。
(後の方が上書となるので結果的に優先順が高くなる)


特定の相手はIPアドレス、ホスト名で指定します
#なお、前述の通り「all」にすれば「全て」の意味になる。

IPアドレスの場合は前方一致検索になる。
・「192.168.1.1」の場合  →  「192.168.1.1」が該当
・「192.168.1」  の場合  →  「192.168.1.0~255」が該当

ホスト名の場合は後方一致検索になる。
・「.xxx.com」の場合     →  「.xxx.com」や「xxx.xxx.com」などが該当
分類:Apache
Apache/お気に入りアイコンエラー・後編
2013年05月09日
【エラーログを抑止する方法】
  エラーを揉み消してしまう。
  Apacheの設定ファイル(httpd.conf)に以下を記述する
  ┌────────────────────────────────────┐
  │Redirect 404 /favicon.ico                                               │
  └────────────────────────────────────┘
  これは、「/favicon.ico」(ドキュメントルート直下のお気に入りアイコン)が
  見つからない(404エラー)の場合、リダイレクトする(がリダイレクト先はない)
  これにより、エラーが揉み消される。
  しかし、アクセスログは欺けない。

【アクセスログを抑止する方法】
  さすがに揉み消せないので、ログに出力させない方向で対処する。
  ┌────────────────────────────────────┐
  │SetEnvIf Request_URI "^/favicon\.ico$" no_log                           │
  │<IfModule log_config_module>                                            │
  │    CustomLog "C:/logs/access.log" common env=!no_log                   │
  │</IfModule>                                                             │
  └────────────────────────────────────┘
  「env」で「no_log」変数(変数名は任意)に条件(お気に入りアイコン)を指定して
  「!=」でこれを除外する形となる
分類:Apache
Apache/お気に入りアイコンエラー・前編
2013年05月08日
Apacheのエラーログに以下のようなメッセージが頻発している時がある。
┌──────────────────────────────────────┐
│[error] [client 127.0.0.1] File does not exist: C:/www/favicon.ico          │
└──────────────────────────────────────┘
と同時にアクセスログには以下が出力されている。
┌──────────────────────────────────────┐
│"GET /favicon.ico HTTP/1.1" 404 209                                         │
└──────────────────────────────────────┘

どうやら、ドキュメントルートの「favicon.ico」(お気に入りアイコン)を
探しにいって見つけられなかったようだ。

「favicon.ico」はHTML上に以下のように設定することにより
そのファイルをお気に入りアイコンとすることができるのだが、
そのApache管轄の設定がないページ(HTML)を開くとそうなるようだ。
┌──────────────────────────────────────┐
│<link rel="shortcut icon" href="favicon.ico"/>                              │
└──────────────────────────────────────┘

ブラウザで比較してみると、IE以外が軒並みエラーとなっている。
┌─┬────────────────────────────────────┐
│○│InternetExplorer(IE)                                                    │
├─┼────────────────────────────────────┤
│×│FireFox、Chrome、Safari、Opera                                          │
└─┴────────────────────────────────────┘

ということで、まとめると以下のような原因だった。
・「favicon.ico」を指定しないページはドキュメントルート配下の「favicon.ico」を
  そのページの「favicon.ico」と見なして読みに行く
  しかし、必要ないのでドキュメントロート配下に「favicon.ico」は置いていなかった
・IEの場合はお気に入り登録時のみ読みに行くが、他は開く都度読みに行く
  ということで、IE以外はページを開くたびに毎回エラーを誘発してしまう

そんな訳で、Apacheのエラーログにエラー出まくりなわけでよろしくない。

解決方法としては、ずばり「favicon.ico」をドキュメントルート直下に
置くというのがあるが、他にも設定で回避できそうだ。

詳しくは次回。つづく。
分類:Apache
C言語/readdir()とqsort()でscandir()を代用
2013年05月07日
「scandir()」は「opendir()、readdir()、closedir()、qsort()」を
まとめてやってくれる便利な関数だが、
「opendir()、readdir()、closedir()、qsort()」で同等のことをやるとしたら
以下のようになる。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【readdir()とqsort()を使用する例】
┌──────────────────────────────────────┐
│    typedef struct {                                                        │
│        char  name[256];                                                    │
│    } S_FILE;                                                               │
├──────────────────────────────────────┤
│    int            count   = 0;                                             │
│    DIR            *dir    = NULL;                                          │
│    struct dirent  *dirEnt = NULL;                                          │
│    S_FILE         dirFile[256];                                            │
├──────────────────────────────────────┤
│    dir = opendir(ディレクトリパス);    // オープン                         │
│    if (dir == NULL) {                                                      │
│        エラー処理;                                                         │
│    }                                                                       │
│    while (1) {                                                             │
│        dirEnt = readdir(dir);  // エントリ情報を取得                       │
│        if (dirEnt == NULL) {  // 取得終了                                  │
│            break;                                                          │
│        }                                                                   │
│        if (dirEnt->d_name[0] != '.') {  // 「.」「..」を除外する           │
│            continue;                                                       │
│        }                                                                   │
│        // ファイル名を取得                                                 │
│        snprintf(dirFile[count].name,                                       │
│                 sizeof(dirFile[count].name),                               │
│                 "%s",                                                      │
│                 dirEnt->d_name);                                           │
│        count++;                                                            │
│    }                                                                       │
│    closedir(dir);  // クローズ                                             │
├──────────────────────────────────────┤
│    // ソート                                                               │
│    qsort(&dirFile,                                // ソート対象            │
│          sizeof(dirFile) / (sizeof(dirFile[0])),  // 件数                  │
│          sizeof(dirFile[0]),                      // 一件あたりのサイズ    │
│          qsortComp);                              // qsort比較関数         │
└──────────────────────────────────────┘
「readdir()」の戻り値にて、「struct dirent」型のポインタに
エントリ情報(ファイル一覧)が取得される
戻り値が「NULL」(終了)となるまで順読みされる
#「readdir()」を使用するには前後に「opendir()」と「closedir()」が必要である
エントリ情報を配列等に採取し(その際、不要なものは読み飛ばししてしまう)、
最後に「qsort()」にて並び替えを行う
「qsort()」は構造体のソート(キーを基準に行ごとソートするような処理)も可能
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【qsort比較関数の例】(ファイル名で昇順・降順にを並び替える)
┌──────────────────────────────────────┐
│int  qsortComp(const void*  s1,                                             │
│               const void*  s2)                                             │
│{                                                                           │
│    if (昇順の場合) {                                                       │
│        return strcmp((char *)(((S_FILE *)s1)->name),                       │
│                      (char *)(((S_FILE *)s2)->name));                      │
│    } else {                                                                │
│        return strcmp((char *)(((S_FILE *)s2)->name),                       │
│                      (char *)(((S_FILE *)s1)->name));                      │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
「qsort()」の第四引数にて、関数を指定することでソート条件を指定できる
関数は別途自分で定義しなければならない(関数名は任意)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
分類:C/C++
C言語/scandir()の使い方
2013年05月06日
「scandir()」を使うと、指定したディレクトリ配下のファイル一覧情報を取得できる。
しかも、抽出や並び替えも同時に行うことができる。
いってみれば、「opendir()、readdir()、closedir()、qsort()」を
まとめてやってくれる便利か関数だ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【scandir()を使用する例】
┌──────────────────────────────────────┐
│    struct dirent  **dirEnt;  // エントリ情報                               │
│    int  count = scandir(ディレクトリパス,  // ディレクトリを指定する       │
│                         &dirEnt,           // エントリ情報を取得する       │
│                         scanExtract,       // 抽出条件関数                 │
│                         scanSort);         // ソート条件関数               │
│    if (count < 0) {  // エラーの場合は件数が-1となる                       │
│        エラー処理;                                                         │
│    }                                                                       │
│    for (int i = 0; i < count; ++i) {                                       │
│        ここで「dirEnt[i]->d_name」を参照すればファイル名が取得できる;      │
│        free(dirEnt[i]);  // 個別に領域解放せねばならない                   │
│    }                                                                       │
│    free(dirEnt);  // 最後に全体を領域解放せねばならない                    │
└──────────────────────────────────────┘
「scandir()」の第二引数にて、「struct dirent」型のポインタに
エントリ情報(ファイル一覧)が取得される。
取得した件数は戻り値で取得できる(「-1」の場合はエラー)
あとはその一覧を参照するだけでよい。
ただし、「scandir()」内にて「malloc()」で領域を確保しているようなので
「free()」で解放しなければならない。
これは、ファイル一覧一件一件ごととそれらを統括する全体について
それぞれ行わなければならないようだ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【抽出条件関数の例】(「.」「..」を除外する)
┌──────────────────────────────────────┐
│int  scanExtract(const struct dirent*  dir)                                 │
│{                                                                           │
│    return (dir->d_name[0] != '.');                                         │
│}                                                                           │
└──────────────────────────────────────┘
「scandir()」の第三引数にて、関数を指定することで抽出条件を指定できる。
関数は別途自分で定義しなければならない。(関数名は任意)
戻り値が「0」の場合は除外されることになる。
#上記の例でいえば、先頭が「.」から始まるファイル名は
  戻り値「false(=0)」となり除外される(それ以外は戻り値「true(=1)」)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【ソート条件関数の例】(ファイル名で昇順・降順にを並び替える)
┌──────────────────────────────────────┐
│int  scanSort(const void*  s1,                                              │
│              const void*  s2)                                              │
│{                                                                           │
│    if (昇順の場合) {                                                       │
│        return strcmp((*(struct dirent **)s1)->d_name,                      │
│                      (*(struct dirent **)s2)->d_name);                     │
│    } else {                                                                │
│        return strcmp((*(struct dirent **)s2)->d_name,                      │
│                      (*(struct dirent **)s1)->d_name);                     │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
「scandir()」の第四引数にて、関数を指定することでソート条件を指定できる。
関数は別途自分で定義しなければならない(関数名は任意)。
但し、ファイル名昇順のソートであれば「alphasort()」が
バージョン名昇順のソートであれば「versionsort()」という関数が用意されている。
#上記の場合は、ファイル名降順もサポートしたいので
  自前でファイル名のソートを実装した場合の例である
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
分類:C/C++
C言語/ファイルのフルパスを取得する方法
2013年05月05日
┌──────────────────────────────────────┐
│ls /aaa/bbb/*.txt                                                           │
└──────────────────────────────────────┘
上記みたいにフルパスで指定すれば、フルパスで結果が得られる
┌──────────────────────────────────────┐
│/aaa/bbb/ccc.txt                                                            │
└──────────────────────────────────────┘

でも、「/aaa/bbb」とかにいて、相対パスつまり「ls」ってだけコマンドを打つと
ファイル名しか取得できない。
┌──────────────────────────────────────┐
│ccc.txt                                                                     │
└──────────────────────────────────────┘

こういう場合は、以下のようにすればフルパスがとれるらしい。
┌──────────────────────────────────────┐
│find `pwd`                                                                  │
└──────────────────────────────────────┘

「find」コマンドに従って絞り込みもできる。
┌──────────────────────────────────────┐
│find `pwd` -name "ccc.txt"                                                  │
└──────────────────────────────────────┘

パイプを使うのもありだ。
┌──────────────────────────────────────┐
│find `pwd` | grep "ccc.txt"                                                 │
└──────────────────────────────────────┘

ちなみにディレクトリを指定するとその配下のファイル名のみが表示されるが。
┌──────────────────────────────────────┐
│ls ../aaa/bbb                                                               │
├──────────────────────────────────────┤
│ccc.txt                                                                     │
└──────────────────────────────────────┘

ワイルドカードで配下ファイルを指定してやると、そこまでのパスも表示されるようだ。
┌──────────────────────────────────────┐
│ls ../aaa/bbb/*                                                             │
├──────────────────────────────────────┤
│../aaa/bbb/ccc.txt                                                          │
└──────────────────────────────────────┘
分類:Linuxシェル
C言語/%sと空文字
2013年05月04日
「printf("%s",…」とかで使う、文字列がはめ込まれる「%s」。
これは、末尾の終端(\0)までを取り込むという仕様なので、
「\0」がない数値項目(int型とか)をぶちこんで例外となる場合がある。
#デバッグログなんかでよくやりがちなミスだ

それじゃ、NULL(\0)入れても大丈夫なんだろ、って早合点して
NULLを直接入れて例外となるのもありがちなミス
#って直接NULL入れる奇特な人は少数かもしれませんが、
  ポインタ変数の絡みで結果的にNULLが入るケースを放置してしまうことは結構ある
┌─┬────────────────────────────────────┐
│×│char*  s = NULL;                                                        │
│  │printf("%s", s);                                                        │
├─┼────────────────────────────────────┤
│○│char*  s = "";                                                          │
│  │printf("%s", s);                                                        │
└─┴────────────────────────────────────┘
「""」を入れるのは大丈夫なんだけどね。
「""」の場合は、ポインタで指したところが「\0」、
「NULL」の場合は、そもそも指すところがない、という違いなのだ。
分類:C/C++
Windows/拡張子しかないファイル名
2013年05月03日
Apacheの設定ファイル「.htaccess」とかは、「.」から始まる
いわば拡張子しかないファイル名である。

これらは、Explorerにおける「名前の変更」ではその名前に変更できない。
どうやら、不正なファイル名が生成されないように予防機能がついているようだ。

ということで、Windows上でこういうファイル名を生成する方法。
(1) コマンドプロンプト(DOSコマンド)からなら「RENAME」で名称変更できる。
  ┌────────────────────────────────────┐
  │RENAME 元のファイル名 .htaccess                                         │
  └────────────────────────────────────┘
    ちなみに、以下で空のファイルを生成できる。
  ┌────────────────────────────────────┐
  │ECHO > .htpasswd                                                        │
  └────────────────────────────────────┘
(2) エディタで名前をつけて保存する
    たいていのエディタでは特に制限がないから保存できるようだ

っていうか、ファイル名を変更とかしないで、
エディタで新規作成して名前を付けて保存するケースが多いから
あんまりこういうことに遭遇することはないというオチのような気がしてきた。
分類:Windows
前へ 1 … 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 … 156 次へ