はてなキーワード: 絶対パスとは
絶対パスになってるじゃねーか
自動で安価をつけて返信するプログラムでもこんなに長く複雑になる(一部抜粋)
/**************************************
以下のCSV_DIR, FILE_PATHS, SETTINGSを書き換えてね。 <h3>o- *************************************/</h3>
//CSVファイルが置かれてるディレクトリのパス。投稿前にエラー出たら大体ここの設定ミス。 例:"C:\\Users\\sakuraimasahiro\\Documents\\iMacros\\Macros\\rentou\\";
'C:\\Users\\USER\\Desktop\\iMacros\\Macros\\rentou\\';
//ファイルのパス。CSVは絶対パスで、拡張子も必要。iimは相対パスでよく、拡張子不要。
const FILE_PATHS = {
textCsv: CSV_DIR + 'textNoAnker.csv',
//レス用投稿文が書かれたCSV。通常とレス用で分けないなら同じファイルを使えばいい。
replyTextCsv: CSV_DIR + 'textReply.csv',
};
baseWaitTime: 5,
//baseWaitTime+0~waitTimeRange(ランダム)だけ待つ
waitTimeRange: 5,
//連投しすぎだと忠告された場合に処理を一時停止させる時間(秒)
waitTimeForAvoidingPunishment: 60 * 30,
//メール
mail: 'sage',
//名前設定
name: '',
//以下、偽装ワッチョイ設定。浪人でワッチョイを非表示にしてるときだけtrueにしてね。
//妙なニックネーム(ワッチョイ、アウアウウーなど)をランダムで決めて付加するかどうか。true=付加する。false=付加しない。
//妙なニックネームの後に付く8桁の文字列をランダムで決めて付加するかどうか。
},
//アンカー無し投稿をするならtrue。しないならfalse。noAnkerPostかreplyPostのどちらかはtrueにすること(両方trueでもOK)。
//アンカー付き投稿(返信)をするならtrue。しないならfalse。もしnoAnkerPostとreplyPostの両方がtrueの場合、投稿は返信が優先され、返信対象が見つからなくなったらアンカー無し投稿をする。
//最初に取得するアンカー無し投稿文CSVファイルの行番号。もし返信用と同じCSVファイルを使うなら-1と入力。
noAnkerPostTextCsvStartRow: 1,
//最初に取得する返信用投稿文CSVファイルの行番号。もしアンカー無しと同じCSVファイルを使うなら-1と入力。
//テキストCSV/返信用テキストCSVの取得行が最終行に達したら最初の行まで戻るかどうか。true=戻る。false=マクロ終了。
//返信する場合、これより小さなレス番には返信しない。返信を投稿すると、この数値は前回の返信先のレス番に更新される。
minAnker: 895,
//返信する場合、名前に以下の文字列を含む投稿にアンカーをつけて返信する(ワッチョイやIPなど名前フィールドにあるものならなんでも可)。配列で複数指定可能。指定無しなら空配列([])。filterNamesとfilterNamesNotIncluded共に無指定ならレス番1から順に返信していく(minAnkerが設定されてればそこから順に)。以下のfilter系は全て併用可能。
//↑とは逆に、名前に以下の文字列を含まない投稿にアンカーをつけて返信する。↑と併用も可能。
//返信する場合、本文に以下の文字列を含む投稿にアンカーをつけて返信する。
filterText: ['自演かな', '自演わらわら', 'スクリプト使うの', '安価ガバ', '>>660', '自演で擁護', '最後' ,'あいうえお', 'かきくけこ', 'さしすせそ', 'なにぬねの', 'はひふへほ', 'まみむめも', 'やいゆえよ', 'やゆよ', 'らりるれろ', 'わいうえを', 'わをん', 'わいうえをん'],
},
//自分のIPアドレスの確認。VPNとかでIPを変更してマクロを動かしてるとき、突然VPNが作動しなくなってIPが元に戻ったときにマクロを止めるためのもの。
//以下の文字列が自分の現在のIPアドレスに含まれている場合、マクロを一時停止する。基本的に自分の本当のIPアドレスを入力。
},
//浪人設定。最後に動作を確認したのは5年くらい前で、今も同じように動作するかは、浪人を持ってないから確認できずわからない。
//浪人にログインしてるかどうかをチェックするかどうか。trueならする。falseならしない。trueにしていてもし浪人にログインしていないことを確認したらログインしにいく。
password: '1234',
},
};
/**************************************
設定箇所終わり。
https://info.5ch.net/index.php/%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%81%E3%81%AA%E3%81%84%E6%99%82%E3%81%AE%E6%97%A9%E8%A6%8B%E8%A1%A8 <h3>o- *************************************/</h3>
/**************************************
・NULL演算子(??)は使えない。論理積(&&)は使える。
・オブジェクトの分割代入はできない。
・importはできない。 <h3>o- *************************************/</h3>
/**************************************
関数 <h3>o- *************************************/</h3>
/**
* ここから始まる。
*/
checkSettings();
var _TextCsvCursors = new TextCsvCursors(
SETTINGS.postSettings.noAnkerPostTextCsvStartRow > 0
? SETTINGS.postSettings.noAnkerPostTextCsvStartRow - 1
: SETTINGS.postSettings.noAnkerPostTextCsvStartRow,
SETTINGS.postSettings.textCsvLoop,
),
SETTINGS.postSettings.replyPostTextCsvStartRow > 0
? SETTINGS.postSettings.replyPostTextCsvStartRow - 1
: SETTINGS.postSettings.replyPostTextCsvStartRow,
SETTINGS.postSettings.textCsvLoop,
),
);
var _LoopStatuses = new LoopStatuses(0, SETTINGS.postSettings.minAnker);
const _MyPosterName = new MyPosterName({
name: SETTINGS.nameSettings.name,
});
const _ThreadUrl = openPromptThreadUrl();
//ループ
while (true) {
SETTINGS.ipSettings.checkIp && checkCurrentIpNotTheIp();
//スレを開く
openUrl(_ThreadUrl.fullUrlHttps());
//浪人にログインする設定なら、浪人にログインしているかどうかを確認し、していなければログインしにいく。
if (SETTINGS.roninSettings.checkLogin) {
}
}
if (SETTINGS.postSettings.replyPost) {
const targetAnkerNumber = createPostDOMList()
.filterPostnumberHigher(_LoopStatuses.currentMinAnker())
.filterByPostername(SETTINGS.postSettings.filterNames)
.filterByPosternameNotIncluded(
SETTINGS.postSettings.filterNamesNotIncluded,
)
.filterByText(SETTINGS.postSettings.filterText)
if (targetAnkerNumber !== null) {
const r = _TextCsvCursors.takeNextRowTextAsReply(targetAnkerNumber);
messageDisplay(`返信対象有り。アンカー先: ${targetAnkerNumber}`);
return {
...r,
updatedLoopStatuses:
_LoopStatuses.updateMinAnker(targetAnkerNumber),
};
}
}
if (SETTINGS.postSettings.noAnkerPost) {
//返信対象無し、或いは返信しない設定の場合。アンカー無し投稿文を作る。
const r = _TextCsvCursors.takeNextRowTextAsNoAnker();
messageDisplay('返信対象無し。アンカー無し投稿。');
return {
...r,
updatedLoopStatuses: _LoopStatuses,
};
}
return null;
})();
if (p) {
//投稿。
nickname: SETTINGS.nameSettings.nickname,
korokoro: SETTINGS.nameSettings.korokoro,
area: SETTINGS.nameSettings.area,
}),
SETTINGS.mail,
p.text,
);
//_TextCsvCursorsと_LoopStatusesを更新。
_TextCsvCursors = p.updatedTextCsvCursors;
_LoopStatuses = p.updatedLoopStatuses.incrementPostCount();
`投稿回数: ${_LoopStatuses.currentPostCount()}`,
`minAnker: ${_LoopStatuses.currentMinAnker()}`,
`今回アンカー無し投稿取得行: ${_TextCsvCursors.currentRows().noAnker}`,
`今回アンカー有り投稿取得行: ${_TextCsvCursors.currentRows().reply}`,
]);
} else {
`返信対象が現われるのを待機中...。`,
`投稿回数: ${_LoopStatuses.currentPostCount()}`,
`minAnker: ${_LoopStatuses.currentMinAnker()}`,
`今回アンカー無し投稿取得行: ${_TextCsvCursors.currentRows().noAnker}`,
`今回アンカー有り投稿取得行: ${_TextCsvCursors.currentRows().reply}`,
]);
}
wait(SETTINGS.baseWaitTime + randomRange(0, SETTINGS.waitTimeRange));
}
}
/**
* 投稿処理と投稿結果を見てリトライしたりマクロ終了したり。
* @param {string} serverName サーバー名
* @param {MyPosterName} _MyPosterName
* @param {string} postMail メール
*/
serverName,
postMail,
_MyText,
retryTimes = 0,
) {
const r =
retryTimes === 0
? new ValuesOfPost(serverName, _MyPosterName, postMail, _MyText).post(
postTo5chTread,
)
serverName,
postMail,
_MyText,
).postSubstring(retryTimes, postTo5chTread, postConfirm);
if (r) {
back();
return;
}
wait(7);
const error = createPostErrorMessage().analyze();
messageDisplay(error.message);
if (error.order === 'KILL') {
kill();
} else if (error.order === 'SKIP') {
return;
} else if (error.order === 'TRUNCATE') {
back();
serverName,
postMail,
_MyText,
retryTimes + 1,
);
} else if (error.order === 'WAIT') {
wait(SETTINGS.waitTimeForAvoidingPunishment);
serverName,
postMail,
_MyText,
retryTimes,
);
} else if (error.order === 'LOGIN') {
serverName,
postMail,
_MyText,
retryTimes,
);
}
return;
}
/**
* 現在のIPアドレスに、SETTINGS.ipSettings.avoidTheIpの値が含まれていないことを確認する。含まれていたらマクロを一時停止。
* @returns
*/
function checkCurrentIpNotTheIp() {
openUrl('https://www.cman.jp/network/support/go_access.cgi');
const _IpAdress = createIpAdressFromCMan();
if (_IpAdress.includes(SETTINGS.ipSettings.avoidTheIp)) {
pause('現在のIPに指定した値が含まれていることを確認。');
}
return;
}
/**
* @returns
*/
if (
SETTINGS.postSettings.noAnkerPost === false &&
SETTINGS.postSettings.replyPost === false
) {
return kill('設定エラー。noAnkerPostとreplyPost両方ともfalseになってる。');
}
if (
SETTINGS.postSettings.noAnkerPostTextCsvStartRow < 0 &&
SETTINGS.postSettings.replyPostTextCsvStartRow < 0
) {
return kill(
'設定エラー。noAnkerPostTextCsvStartRowとreplyPostTextCsvStartRow両方とも-1になってる。',
);
}
if (
SETTINGS.postSettings.noAnkerPostTextCsvStartRow === 0 ||
SETTINGS.postSettings.replyPostTextCsvStartRow === 0
) {
return kill(
'設定エラー。noAnkerPostTextCsvStartRow/replyPostTextCsvStartRowの初期値は-1或いは1以上で。',
);
}
}
/**
* 入力フォームを表示して入力されたスレのURLを受け取る。
*/
function openPromptThreadUrl() {
const url = prompt('スレURLを入力');
}
/**
* 開いてるスレのレス全て読み取ってPostListインスタンスを作って返す。
* 重すぎるので使うのやめ。どうやらインスタンスの大量生成が原因な模様。
*/
const posts = window.document.getElementsByClassName('post');
return new PostList(Array.from(posts).map((e) => new Post(e)));
}
/**
* 開いてるスレのレス全て取得してPostDOMListに格納して返す。
* @returns
*/
function createPostDOMList() {
const posts = window.document.getElementsByClassName('post');
for (let index = 0; index < posts.length; index++) {
//HTMLCollectionからElementを1つずつ抽出して配列に。
arrPostDOMList.push(posts.item(index));
}
return new PostDOMList(arrPostDOMList);
}
/**
* 開いてる投稿結果画面に表示されてるエラーを読み取ってPostErrorMessageインスタンスを作って返す。
*/
function createPostErrorMessage() {
window.document
パスタ茹でをオートメーションで自動化していつでも美味しい茹でたてパスタが食べられるようにって考えた私の最強問題解決ソリューションは
パスタクッカーと電気ポットの組み合わせが強くない?って最終ファイナルアンサーで
あとは導入待ったなし!ってところなんだけど、
電気ケトルでは2リットルいっぺんに沸かせるケトルが世の中になくて、
あれもあれで沸いた瞬間を見計らってお湯を使わないと行けないし、
ちょっとお湯が沸くのを待ち構えていないと行けないじゃない。
目を離しても大丈夫!ってファクトリーオートメーションを達成したいソリューションなのね。
それで考えたのが、
大量にお湯が沸かせる電気ポット!
これだと余裕で2リットル以上のお湯が一度に沸かせて、
目を離せるわけじゃない。
それで、
パスタクッカーにお湯ぶち込んで
これは時間かかるのは致し方ないとして、
あとは保温調理風茹であがりを待つだけ!って
これしか勝たんわ。
たしかに、
誰が見ても鍋!って思えるような鍋で
コンロにお湯を沸かしてパスタをぶち込んで茹でる!ってのが一番正攻法でママーパスタなんだけど、
これはコンロに火を掛けたら目が離せないじゃない。
私はパスタを茹でている時間何かしたい時間に費やせるためのパスタオートファクトリーを達成したいの。
炊飯器的に自動的にパスタが茹で上がるソリューションを考えているの。
でもさー、
パスタクッカーと電気ポットを新たに手に入れなくちゃ行けない先行投資のイニシャライズがあって、
時は金なりと言うから、
タイ米を叩いて大枚で導入してみてもいいのかしら?って思うけど、
これが毎日ファクトリーオートメーションでパスタを必要なぐらい毎日食べてるか?って言われると
いや、
パスタが気軽に自動的に茹で上がる仕組みがないから食べていないだけで、
もう毎日パスタも見るのみ嫌だよマンマミーア!って言いそうなレヴェルまで食べて食べて食べ続けることが必要なのよね。
そのソリューショングッズのパスタ自動茹でシステムを完成させたら、
そんな作戦を考えているのよ。
お米なら簡単に無洗米勝手に炊ける炊飯器ソリューションがレボリューションで
お米を炊く仕掛けをして、
お米が炊けたらなんかもう食べたくなくなった気持ちを解決するソリューションってないわけじゃない。
だから結局炊けた炊けた!って喜んでいても忘れて1週間保温しっぱなしで黄色くなったご飯が美味しい美味しいって食べる、
あれもあれで困るし、
その間に
パスタ食べたくなくなった気持ちを帰せ!ってことは少ないと思うから、
今でこそ文明の利器を駆使して
でもあんまり道具が何点も増えるのものを増やさない暮らしをお休みまで見つめるライオンと違って、
増えるのも良くないなーっても思うのよ反面ね。
だから、
実際にパスタ自動茹でソリューションシステムを完成させて暮らしている
最強のパスタ達人に出会ってお話を聞くまではお預けなのかも知れないわ。
でもこのパスタ茹で自動ソリューションシステムは秀逸だと思うんだけどなぁ。
もうちょっと
うふふ。
朝めちゃくちゃ寒くなかった?
ここぞってときの
ホッツ白湯ウォーラーをふーふーしながらゆっくり飲んで温活ってところよ。
すいすいすいようび~
今日も頑張りましょう!
32歳、営業職です。
プログラムとかなんもわからんちんなのですが、アプリを作りたいと思いたちアプリを
作ってみました。
とりあえず、アプリのランキングを見ていると、エロ系がやっぱり強いと思って、エロは正義!の名の下に
簡単にアプリを作るために、まずは簡単に作れるフレームワークを探す所から始まります。
フレームワークってなんですか?
それはね、なんだかわからないけど、簡単につくれるようになるものなんですよ。
詳しくは、
外人「システムを作るときに、よく利用する機能とか、構造とか、予めあると便利だろ?
俺が作っといてやったよHAHAHAHAHA」
っていう感じのものだそうです。
プログラミングなんてわからんちんだけど、HTMLくらいは作れるよ!
そんなあなたにPhoneGap(http://phonegap.com/)ということで、
とりあえずPhoneGapを使って見ることに。
でも、実際使ってサンプルを作ったりしてみると、動くは動くんだけど、
色々やろうとすると、Web上にあるドキュメントが古いのか、PhoneGapが最近になって
突如バージョンがあがったせいか、書いてる通りにやってみてもできない。
とりあえずiPhone Developer登録は既に完了していたので、Xcodeをつかってやるぜ!
俺は赤の扉を選ぶぜ!と思ったがはてさてどうすりゃいいのか。
HTMLをプロジェクトに追加するのはドラッグ&ドロップすれば完了だ。
その際にダイアログが出てくるので、"Create folder references for any added folders" を選択しておくと
元々のフォルダ構造とかが失われずそのまま追加できるのでいいぞ。
ほんでもって、UIViewControllerというのを作成する。
IBOutlet で UIWebView を利用するためのオブジェクト変数を用意しておいて、InterfaceBuilderから接続をする。
Files's Owner とかを右クリックして出てきた変数名と画面上についかしたUIWebViewをマウスでつなぎあわせれば
接続できるぞ。なんて簡単なんだ。
一番最初に行われる初期化の処理は viewDidLoad にでも書いておけばいいらしいのでここに書く。
UIWebViewはURLの書式になっていないと開けないようなので、それを調べることから始まる。
アプリ内に追加したリソースファイルは、アプリのデータに内皮されるらしい。
アプリが展開されるフォルダというのは、デバイスにより様々なのだが、そこから内皮されている
ファイルを取得するための処理というのがあるのでそれを利用する。
NSString *html_path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory@"web"];
これでwebフォルダ内にあるindex.htmlファイルの絶対パスを教えてくれるというわけだ。
あとはこれを読みこませればOK。
[web loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:html_path]]];
NSURL というのがURL書式を記述するためのオブジェクトだと思っていただきたい。
ここではローカルファイルのパスを拾うため、 fileURLWithPath とするのがポイントだ。
file://nantarakantara/index.html みたいな書式になるんでしょうね。
なんだか色々理由はあるみたいなんですが、そうですかだめですか。
善は急げで、AndroidSDKとEclipseというものをダウンロード。
昔は色々設定が必要だったが、いまは開けば即使えるようになったらしい。便利便利。
こっちの場合も同じようなやつがあるんでしょう、ほらったWebViewこれを使えばいいらしい。
XCodeのときは、いかにもアプリの画面を作れば完成って感じだったけど、Androidの場合は
Layoutファイルというのを使わないといけないみたい。なんかこれはHTMLみたいな記法だな。。
どうなってんだかよくわかんないですけど、Layoutを作成して、WebViewを配置、
Androidの場合は、assetフォルダというのをつくってあげて、そこにHTMLファイルを
置けばいいらしいですよ。なるほどね。
WebViewでの開き方は、assetフォルダを直接開けばいいだけらしい。いえーい!
layoutに配置したWebViewをオブジェクト変数に呼び出して、、、
webView.loadUrl("file:///android_asset/web/index.html");
ひらいたーおっけーーーーーーー。
だけども、リンクを開くとブラウザが開いてしまうなあ。どうすればいいのこれは。
調べてみるとこうすればいいらしい。
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
これで無事、WebView内で画面遷移するようになりました。
やっほー
そんで、なんとかつくりあげて、申請・・・
とかないんですね、公開したら公開されましたw
ていう感じで始めてつくってみたんで
よかったらダウンロードしてみて下さい!
https://play.google.com/store/apps/details?id=ff.appgroup.app001_hrenai
スワイプだけでフォルダー内の全ファイルを閲覧。すべてのファイルが横に並んでいる。[[参考:m>notes]]のように。
縦にファイルをつなげる。これはファイルのグループ化。これも[[参考:m>notes]]。親となるファイルに独自記法が書かれていればつながる。親子管理用のデータは持たない。(Dropboxなどで他端末にコピー、デスクトップアプリで開いた時に有効になるように相対パスでファイル指定)UI上は記法ではなくファイル選択(親を開いて子を選択・子を開いて親を選択。選択肢にはファイル名によるフィルタリングをしたい。できればファイル内容の全文検索でも。UIは統合できるはず)親を子にすれば子が孫になるように。見た目はリスト、でもデータ構造はツリー。
設定項目に「ホームフォルダー」。その外にも出られる。制限しない。戻れることが大事。
自動命名・自動保存。ファイル名がどうしても付けられないなら適当なファイル名で適当なところに残す。開きやすければいい。
アンドゥ。「キーロガーと併用して」で済ませるのもあり。
起動時のビュー(最小化から復帰した時除く)は設定可能。ビュー別にホームアイコンを作成することも可能に。
モーダルダイアログ排除。またはダイアログ外タップで閉じられるように。
アプリにカーソルキー不要。大きく表示するビューを用意。ダブルタップや長押しで切り替え。文字を打つときには戻るように。でもこれはAndroidに任せるべき。
カーソル位置が分かりにくい上に意図しない位置へ行くのでアンダーライン必須。でもアンダーラインよりも背景色を行ごと変更したほうが分かりやすい。背景に横罫画像も使える。
検索とキーワードハイライトを統合。検索キーワードは検索のたびに追加。検索キーワードの目次生成。置き換えでも追加。置き換えた箇所が強調表示になる。自動的に追加されるハイライトの色はモノトーン。追加されるたびに古い強調表示は弱くなる。操作で別の色に変更できればいい。強調箇所は独自形式のデータにするしかない。どうせ他のアプリでは再生できないのでこのアプリ専用データ。
[[ファイル名(拡張子不要)]]でリンク。最初の「.」以降不要。あってもいい。それで重複が発生したらタップ時にリスト表示。選ばせる。
自動リンク。同一フォルダー内のファイル、ファイルのあるフォルダーからの相対パス、ホームフォルダーからの相対パス、絶対パスに。
ファイルを集めて一冊の本に。リンクを応用、見出し(正規表現で定義)へのリンクを自動生成して1つのファイルに書き出し。1フォルダー内のファイルだけでいい。そのファイルの冒頭には「本」ファイル用の見出しを入れる。その見出しだけの本を作れば本の本、同じプログラムで本の本の本の本も生成可能。設定項目が増えそうなので不要。
1. のあとで改行すると 2. が生成されるような。
タブストップ調整。タブ文字1つで表組み。LTSVが崩れのない表になるような。
スクロールバーには目次を表示したい。ドラッグ中に半透明で画面の右側だけを使って表示するとか。
RIGHT:[[:t/App]]
----
togetterがchromeが固まるくらい重いのと、書いてある内容に同意できてもエタ東となる4時の組み合わせは気分が悪いので、自分用に。
最初に書いておくと、これは特にpixiv擁護ではない。というより、擁護できる部分は特にない。
pixivを擁護したがっている人たちというのがいて、連日出てくる問題を鎮火させようと頑張っている。
カオスラウンジとズブズブだったpixivも悪の企業であると認めず、pixivは悪くない、pixivは俺たちの居場所だ、と信じて自分たちの立場を守ろうとする。(俺正義タイプ)
本の宣伝をしたいが代替サービスのユーザーがまだ少ない。pixivを宣伝用に使い続けるしかないのからpixivを守りたい。(我欲タイプ)
pixivとかユーザーのことなんて全くどうでもいいけど、批判に対して反対意見を言える俺かっこいい。(自己顕示タイプ)
大体想像できる動機はこんなところ。
メンツは固定しているないが、毎度の騒動で発生源となっているtogetterまとめを網羅的に眺めると、誰が鎮火しようとしているのか分かりやすい。
はてブでいうとb:id:sa_tie、b:id:katsura_1、b:id:tailtame辺りが該当。彼らを駆り立てているものは一体何なのか。(なお、エタ東も方向性が違うだけで同類にカテゴライズしている)
もっとも動機が不純だからといって、成すことが正しければ良い結果をもたらすこともあるし、独善が「悪事」としか呼べない暴走を引き起こすこともある。評価は人による。
pixivの新規登録画面は極めてシンプルで、pixiv idの用途については特に記されていない。(※要改善)
登録するとユーザーにはユニークな数字のidが付与されるので、pixiv idはログイン用のみだと考えている人は少なからずいるようだ。
実際にはpixiv id名でディレクトリが作られるほか、スタックフィード(活動履歴)のid、アカウントを共用するpixivブログや、姉妹サイトdrawr(flashで手書きできるサイト)のidとして利用されている。
pixiv idを外部から見られないものとして、個人名を使うなどする人もいて、問題となったことは過去に数度ある。id変更の機能追加をするという話もあったが今のところは実現していない。
今回の騒動の発端となったのはこのpixiv idが画像の絶対パスから参照可能だ、という最初期から判明していたことを何度運営に要望を出しても改善されないまま放置されたことに業を煮やしたことユーザー達のtwitterである。
これを、「最初期から判明していたことだから今更問題ではない」と擁護する連中が現れた。
「idは最初期から漏洩するような仕様で、スタックフィードなどからidを参照することも可能だ」と判っても問題点を把握できないユーザーが多数いたことで、危機の周知は次段階に移る。
「IDとパスワードを同じにしている人は危ない。プレミアムユーザーならクレジット番号などの登録もしているので危ない。」と危険を訴えた。この辺りから「ただの言いがかりレベル」などと鎮火ツイートが広がる。
現在のPCスペックの技術の向上は目覚しく、家庭用でもハイスペックなPCがあれば簡単なパスワードであれば数分~数十分で破ることもできるとされる。
が、それはメモリ内で高速に試行できるローカル環境上の話であって、web上のパスワード認証に対して必要とする時間は全く別物という視点が抜け落ちていて、とても現実的ではない。
だが、総当たりなどせずとも、簡単な単語やIDと同じパスワード、誕生日などであれば簡単にログインできてしまう可能性がある。
それを、「例えローカル上で10万回/秒でログイン試行できるPCでも、web上のパスワード認証に対しては通信とサーバーレスポンスがボトルネックとなって100回/秒程度のパフォーマンスしか発揮できないと思う。並列で大量にリクエストを殺到させればサーバーが落ちるだけだし、そもそも膨大なオーダーのログイン攻撃が仕掛けられれば、突破するより前にファイヤーウォールが異常を関知するか、サーバー管理者が気付く。そもそもイラストコミュニティサイトに対して逮捕されるリスクを犯して潜入したところで、成りすまして暴言コメントを書いたり個人情報を抜く程度で、不正アクセスのリスクにリターンが見合っていないわけで…。」
などと問題点をすり替えて、指摘する側がさも間違っているかのように発言を繰り返す。
大手ポータルサイトや銀行、携帯キャリア、有料ポイントを運用するネトゲなどであればそれなりに堅牢なログイン構造にするのが当然で、既に大手のお絵描きコミュニティ、しかもカードの支払まで行われるサイトにパスロックがないというのが問題でないはずがない。
admin.pixiv.net他に接続するとグローバルIPからでもログイン認証が出てくるというもの。発覚したのは実は1年も前だという。今回twitter等で公になってからも1時間程度は誰もがアクセス可能であった。
あくまでログイン認証画面が出てくるだけで、ID/パスワードが判明したわけでもなく、webのログイン認証に対するブルートフォースは非現実的なのは変わらないが、「外部からadminツールにログイン可能」というセキュリティ意識の無さが露呈し、大騒ぎとなる。
更に話が広まる際には「adminツールが流出した」「バックドアが仕掛けられた」「ログインにキーロガーが仕掛けられている」「アクセスするとウイルスを仕込まれる可能性がある」「今すぐ退会せよ」など虚実入り乱れた話となる。
普通に考えれば、外部からアクセス可能な状態で晒され続けたという事態が発覚した時点でサーバーを落として対策を取るはずなのだが、隠蔽体質に定評のあるpixivが何のアクションも起こさない為、念のためアクセスを控えるよう呼びかける。
「そこまで大事になっているのであればサーバーを落とすわけで、実害はない」などと見当違いな「俺の脳内のpixivのセキュリティ安全神話」ツイートが擁護派から出てくる。
admin.ads.pixiv.orgに接続すると「It workssl!」と表示されるもの。これがapacheのデフォルト表示「It works!」と異なることから、「何者かに書き換えられたか、運営が謎のミスをしたのか」と疑惑が生まれる。
ads.pixiv.orgは広告関連のサーバーのようだが、侵入された場合は他のサーバーも同様に危険である可能性が高く、「個人情報やカード情報が抜かれる危険性もある」と指摘されると「万が一侵入されていても個人情報が流出する可能性は低い」と根拠のないpixivの言い訳を持ち出す。
カード情報は決済代行会社が保存していると運営から「なぜか」一部ユーザーにメールで通知されていたようで、ここまでの騒ぎになっておきながらサイトトップでも発表しないなど、さらに不信感が募る。
「IDが漏洩する危険性がある」という問題点から、罪のないユーザーが被害に遭うことを防ごうしたものの、サービス開始時からの仕様で改善される望みが薄い。
さらに管理者ページが外部から閲覧できたことは、あってはならないセキュリティ意識、にもかかわらず、「批判は的外れで間違いだらけ」というまさに的外れな擁護ツイートが広まる。
ここまでサンドバックになってて何も発言せずパスロックを実装するpixivはある意味凄いが、その沈黙がさらなる疑惑を生んでいることにいつ気が付くのか。
會川昇 浅羽通明 東浩紀 庵野秀明 石@森プロVS宝島問題 石@森プロVSマンガ夜話問題 伊集院光 エヴァ現象 大塚英志 大塚VS岡田問題 大月隆寛 大月アニメ 岡田斗司夫 落合信彦
加藤典洋 ギャルゲー 切通理作 桑島法子 呉智英 小林治 小林よしのり 小林よしのりVS宅八郎 小森まなみ 小谷野敦(つづき)
サイコ版権引き上げ騒動 齋藤環 桜井亜美 白倉由美 白倉VS桑島問題 セカイ系
大地丙太郎 田中芳樹 富野由悠季 富野伝説 永井豪VSマンガ夜話事件 永江朗 波乗り! アニメジャーナル
ブンガク 宮崎哲弥 宮崎駿 宮台真司 村上春樹 福田和也 藤岡信勝 安彦良和 SFである・ない論争 TVゲーム