Apacheでアクセス制限をする

Apacheでアクセス制限をしようと頑張った結果こうなりました.

1. やりたいこと


私がやりたかったのは以下のことです.

  • /docroot はアクセス制限有り.
  • /docroot/foo はアクセス制限有り.
  • /docroot/bar はアクセス制限無し(省略.

ここでのアクセス制限とは,192.168.0.0/24なら自由にアクセスできる,ただしそれ以外の場合はBASIC認証が必要というやつです.

また,/docroot/{foo,bar}は指定した拡張子(ここでは.htmlと.php)のみ外部から参照できます.

2. 勘違いしてたこと


アクセス制限がホスト制限と認証しかないということです.
とかとかはただ単にその2種類の制限を操作するかどうかのif文でしかなかった,というのに気付くのにえらい時間がかかってしまいました.

3. アクセス制限書く


  Order Deny,Allow
  Deny from All
  Allow from 192.168.0.0/24

  AuthUserFile /path2pass
  AuthName "Nyan"
  AuthType Basic
  require valid-user

  Satisfy Any

4. 拡張子の制限を書く


  
    Order Deny,Allow
    Deny from All
    Satisfy All
  
  
    Order Deny,Allow
    Allow from All
    Satisfy Any
  
  
    Order Deny,Allow
    Allow from All
    Satisfy Any
  

は同時に適用&上書きされるらしいのでこう書きました.
ちなみに,""はttp://example.com/foo/の様にDirectoryIndexを省略した時用です.

5. モウヒトコエ

ただし上記のままではttp://example.com/fooの様に最後にバックスラッシュが付いていない場合にアクセスできません.
なぜならにfooとしてマッチしてしまうからです.
そこで,にしてもいいのですが,よくわからないのでfooを許可します.

  
    Order Deny,Allow
    Allow from All
    Satisfy Any
  

6. 最後に

これだとttp://example.com/fooでアクセスできますが,ttp://example.com/foo/fooにもアクセスできてしまいます.
なので,次のやつを書きました.


  Order Deny,Allow
  Deny from All
  Satisfy All

の後に評価されるので上書きされてアクセスが禁止されます.
これでだいたいうごくとおもいます.
ちゃんと動いていなかったり,もっと上手い方法がある,まちがってる,とか教えていただけるとうれしいです.
mod_rewriteとかでできそう?


あと,私が実際にやった環境ではVirtualHostがからんでたりするのでちょっと違うかもしれないです.

7. 関係ないこと

httpd.confを0から書くというのをやってみたらおもしろかったです.
Apache3.0になるとこの辺をもっときれいに書けるみたい?


参考書:Apache公式サイト
Apacheセキュリティ
Apacheクックブック

1: Best Software Writing


読みました!


とても面白かったです.特にソーシャルソフトウェアについての内容はとても興味深いです.あとWIPOの話など読んでいて面白い(そして知るべきである)ストーリなどが多くありとても勉強になりました.

BEST SOFTWARE WRITING

BEST SOFTWARE WRITING

Boost.PtrContainer


Boost.PtrContainerのptr_array<>というのを使ってみました.
中身をポインタとして保持して,アクセスする時はポインタの先の参照を返してくれる粋なやつです.


ptr_array<>はptr_vector<>とかに比べてちょっと特殊かも.
実体の供給方法とかnullの保持とか.


>>|cpp|

#include
#include
#include
#include
#include

const unsigned size = 10;

int main(){

  boost::ptr_array numbers;


  // 要素(実体)があるかどうかチェックできる.当然無い.
  assert(numbers.is_null(1) == true);


  // arrayの場合はpush_backとか当然できないので,
  // replaceという関数で置き換えてnewする.
  for(unsigned i=0; i(std::cout, ","));
  std::cout << std::endl; // 0,1,2,3,4,5,6,7,8,9,

}

|

PropertyTreeのptreeをiterationする


ちょっと調べたのでメモです.

以下の様なiniファイルのKeywordsを順番にiterationしていくのが目的です.

// trends.ini
[Keywords]
触手 = 秋猫
しまぱん = 桜花
縞ぱん = 桜花
縞パン = 桜花

#include <iostream>
#include <boost/property_tree/ini_parser.hpp>

namespace ptl = boost::property_tree;

int main(){

  ptl::ptree pt;
  read_ini("trends.ini", pt);

  const auto& keywords = pt.get_child("Keywords");
  auto it = keywords.begin();
  const auto end = keywords.end();

  for(; it!=end; ++it)
    std::cout << it->first << " : " << it->second.data() << std::endl;

// 触手 : 秋猫
// しまぱん : 桜花
// 縞ぱん : 桜花
// 縞パン : 桜花

}


・・・終わりです><.

AnyPtrとxtal::undefinedの比較

バージョンはXtal Unofficial Wikiのr429です.


Xtalスクリプトで定義したbooleanの値を取得しようとした所,undefinedと==が成り立っちゃいました.

// .xtal

bool_true : true;
bool_false : false;

// .cpp

const xtal::CodePtr& code = load_and_call(the_file);

const auto& bool_true = code->member(Xid(bool_true));
const auto& bool_false = code->member(Xid(bool_false));

assert(bool_true != xtal::undefined); // こっちは期待通り
assert(bool_false == xtal::undefined); // あれ?

// 解決策?
assert(!xtal::is_undefined(bool_true));
assert(!xtal::is_undefined(bool_false)); // パーペキ


てっきりoperator==で良いのかと思ってましたが,ダメなんですね.

ソースコードを読んでたらxtal::is_undefined(...);というのを発見.
これを使ったら期待通り動いてくれました.

少し前に誤って消したファイルを復旧する


最近gitを使い始めてます.
そして日記を書きたいので,gitでこんなことをやったというのを書こうかと.
正しい(最適)かは分かりませんが….


いつのまにか必要なファイルをdeleteしてコミットしてしまったようで,ファイルfoo.cppがトラックから消えてました.

調べたところ,コミットabcdでコミットしてしまったようなのでrebaseして復旧します.


// 変更をあっちへぽい!(((ノ≧∇≦)ノ
git stash

// abcdの親からrebase
git rebase -i abcd^

// abcdを編集する
-pick abcd
+edit abcd
pick some

// foo.cppをabcdの親から復旧
git reset abcd^ foo.cpp

// abcdへ編集コミット
git commit --amend

// foo.cppをindexからworking treeへ.
git checkout foo.cpp

// rebaseを終わらせる.
git rebase --continue

// 変更をヽ(・o・ヽ) キャッチ!!
git stash pop


git helpで調べながらやったらこうなりました.
もっとスマートな方法とかあるのかな.
というかこれは良いのかな.

普通のBoostプログラミング

この記事はC++ Advent Calendar jp 2010 : ATNDの7日目の記事です.
他の記事と比べちゃダメです.
わたしはほんわか担当なので.


テーマは(自分の力量制限により)「普通のBoostプログラミング」です.
最近Boostを使ったコード片の比較的つまらなくなさそうな部分をまとめてみました.


やりたいことは以下の事です.

  • このシステムには周期があり,毎周期毎に変化するデータXが入力される
  • それとは別に固定のデータ列Yがある
  • 新しい方から一定周期F毎のデータXと,先頭から順のデータYを最大N個同時に取得したい


図0.大変分かりにくい状況画像


データXとデータYはセットにして使うので同時に取得しています.
また,データYは固定なのになぜ別の場所から取得しないのかというと,(実は)密接に関連しているからです.
状況的に良く分からないかもしれませんが,そういうものだと思って下さい.


まずデータXの保存を考えます.
データXは最新F*N個(くらい)を覚えていれば良く,それより古いデータは破棄して構いません.
そこでBoost.CircularBufferが使ってみたかった良さげなのでこれに格納します.

データYはN個です.
データXに依存するか否かに関係なく個数は固定なので,std::arrayで問題無いです.

データの取得はBoost.RangeのIteratorRangeで行います.
データXは(F*n){nは0〜N-1}番目を取得したいので,それ以外をスキップするイテレータを使います.
インクリメントする毎にF進むイテレータを作った方が良いかもしれませんが,今回は既にあるboost::permutation_iteratorを使います.
最後に,データXのイテレータとデータYのイテレータを同時に返す必要があるため,正にそのためにあるboost::zip_iteratorでまとめます.


まずはtypedefなどをしちゃいます.
#元がクラスなのでちょっと名前とかあれですが.

#include <array>
#include <cstddef>
#include <boost/circular_buffer.hpp>
#include <boost/iterator/permutation_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>

namespace {

  const std::size_t F = 12;
  const std::size_t N = 5;

}

struct X{};
struct Y{};
typedef boost::circular_buffer<X> X_container;
typedef std::array<std::size_t, N> X_indices_container;
typedef std::array<Y, N> Y_container;
typedef boost::zip_iterator<
  boost::tuple<
    boost::permutation_iterator<
      X_container::const_iterator,
      X_indices_container::const_iterator
    >,
    Y_container::const_iterator
  >
> const_iterator;

X_container,Y_containerはそれぞれデータX,Yを格納する型です.
boost::permutation_iteratorは2番目のイテレータで指定した順番に1番目のイテレータにアクセスするイテレータです.
なので何番目にアクセスするか,をX_indices_containerに格納してそれをpermutation_iteratorに渡しています.
最後に,Xを取得するイテレータであるpermutation_iteratorとY_container::const_iteratorをtupleにまとめてboost::zip_iteratorに与えます.
std::tupleでなくboost::tupleなのは,std::tupleがboost::zip_iteratorの要件を満たしていないからです.


次に変数宣言と初期化をします.

#include <functional>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm_ext/overwrite.hpp>
#include <boost/range/counting_range.hpp>

X_container Xs;
Y_container Ys;
X_indices_container X_indices;

using boost::adaptors::transformed;
using std::placeholders::_1;

boost::overwrite(boost::counting_range(0U, N)|transformed(std::bind(std::multiplies<std::size_t>(), _1, F)), X_indices);

Ys = get_Y_values();


Xsは周期毎にデータが追加されるので空で良いです.
Ysには適当な値を入れます.
X_indicesにはXs内の取得する値のインデックスを入れます(つまり,F*0, F*1, F*2, ...F*(N-1)です).


次に毎周期毎にデータXを追加する関数です.

void push(const X& x){

  Xs.push_back(x);

}

はい.


次に値を取得する関数です.
ラスボスです.

#include <iterator>
#include <boost/assert.hpp>
#include <boost/range/iterator_range.hpp>

boost::iterator_range<const_iterator> get(){

  const std::size_t valid_size = static_cast<std::size_t>((Xs.size() + F - 1) / F);
  BOOST_ASSERT(valid_size <= N);

  const auto xs_begin = boost::make_permutation_iterator(Xs.begin(), X_indices.begin());
  auto xs_end = xs_begin;
  std::advance(xs_end, valid_size);

  const auto ys_begin = Ys.begin();
  auto ys_end = ys_begin;
  std::advance(ys_end, valid_size);

  return boost::make_iterator_range(
    boost::make_zip_iterator(boost::make_tuple(xs_begin, ys_begin)),
    boost::make_zip_iterator(boost::make_tuple(xs_end, ys_end))
  );

}

最初はデータがF*N個ないので,始めに取得するデータの個数を計算しています(Xs.size() + F - 1をNで割って切り捨てです).
次にXsとYsのイテレータを作成しています.
endはbeginから取得するデータの個数分だけ進めています.
最後にzip_iteratorを作りそれをiterator_rangeとして返しています.


ちなみに,データの取得は次のようにできます.

#include <boost/foreach.hpp>

BOOST_FOREACH(const auto& elem, get()){

  const X& x = elem.get<0>();
  const Y& y = elem.get<1>();

}


あとがき.

はい,普通にBoost.CircularBuffer,Boost.Iterators,Boost.Rangeを使ってみました.
Boost.Iteratorsの使い道が良く分かってなかったのですが,クラス内で保存しているデータを外部へ公開する時にちょっと変換したい場合などに便利ですね.むしろそれ用ですかね.


最後に.
信じられないかもしれませんが,この記事はC++ Advent Calendar jp 2010 : ATNDの7日目の記事です.


壁|oノωノ) )))))))・・・イヤーン♪