オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /aquaskk/trunk/src/engine/dictionary/SKKAutoUpdateDictionary.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations) (download) (as text)
Fri Aug 15 15:19:04 2008 UTC (15 years, 9 months ago) by t-suwa
File MIME type: text/x-c++src
File size: 4691 byte(s)
 r390@milonga:  t_suwa | 2008-08-15 23:44:45 +0900
 - 存在しない辞書を指定すると毎回タイムアウトする不具合を修正
 
 r391@milonga:  t_suwa | 2008-08-16 00:18:51 +0900
 - 移行したファイルの所有者が root になる不具合を修正
 

1 /*
2
3 MacOS X implementation of the SKK input method.
4
5 Copyright (C) 2007 Tomotaka SUWA <t.suwa@mac.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21 */
22
23 #include "SKKAutoUpdateDictionary.h"
24 #include <sys/stat.h>
25 #include <cerrno>
26 #include <sstream>
27 #include <fstream>
28 #include "socketutil.h"
29
30 // 辞書ダウンロードクラス
31 class SKKAutoUpdateDictionaryLoader : public SKKDictionaryLoader {
32 bool first_;
33 short port_;
34 std::string host_;
35 std::string url_;
36 std::string path_;
37 std::string tmp_path_;
38
39 virtual bool run() {
40 if(first_) {
41 notify();
42 }
43
44 net::socket::tcpstream http(host_, port_);
45
46 if(request(http)) {
47 int length = content_length(http);
48
49 if(download(http, length)) {
50 notify();
51 }
52 }
53
54 return true;
55 }
56
57 bool request(net::socket::tcpstream& http) {
58 char timestamp[64];
59 struct stat st;
60
61 if(stat(path_.c_str(), &st) != 0) {
62 st.st_mtime = 0;
63 }
64
65 // HTTP 日付を生成する(RFC 822, updated by RFC 1123)
66 //
67 // 例) "Sun, 06 Nov 1994 08:49:37 GMT"
68 strftime(timestamp, sizeof(timestamp),
69 "%a, %d %b %Y %T GMT", gmtime(&st.st_mtime));
70
71 http << "GET " << url_ << " HTTP/1.1\r\n";
72 http << "Host: " << host_ << "\r\n";
73 http << "If-Modified-Since: " << timestamp << "\r\n";
74 http << "Connection: close\r\n";
75 http << "\r\n" << std::flush;
76
77 return http;
78 }
79
80 int content_length(net::socket::tcpstream& http) {
81 int length = 0;
82 std::string response;
83
84 while(std::getline(http, response) && response != "\r") {
85 if(response.find("HTTP/1.1") != std::string::npos) {
86 std::istringstream buf(response);
87
88 // "HTTP/1.1 200" を期待する
89 buf >> response >> response;
90 if(response != "200") {
91 while(std::getline(http, response)) {}
92 break;
93 }
94 }
95
96 if(response.find("Content-Length") != std::string::npos) {
97 std::istringstream buf(response);
98 buf >> response >> length;
99 }
100 }
101
102 return length;
103 }
104
105 bool download(net::socket::tcpstream& http, int length) {
106 if(!length) return false;
107
108 std::string line;
109 std::ofstream ofs(tmp_path_.c_str());
110
111 while(std::getline(http, line)) {
112 ofs << line << std::endl;
113 }
114
115 struct stat st;
116 if(stat(tmp_path_.c_str(), &st) < 0 || st.st_size != length) {
117 return false;
118 }
119
120 if(rename(tmp_path_.c_str(), path_.c_str()) != 0) {
121 std::cerr << "SKKAutoUpdateDictionaryLoader::download(): rename failed: errno="
122 << errno << std::endl;
123 return false;
124 }
125
126 return true;
127 }
128
129 void notify() {
130 SKKDictionaryFile tmp;
131
132 if(tmp.Load(path_)) {
133 tmp.Sort();
134 NotifyObserver(tmp);
135 } else {
136 if(first_) {
137 first_ = false;
138 NotifyObserver(tmp);
139 }
140 }
141 }
142
143 public:
144 SKKAutoUpdateDictionaryLoader(const std::string& location) : first_(true), port_(80) {
145 std::istringstream buf(location);
146
147 buf >> host_ >> url_;
148
149 buf.ignore(1);
150 std::getline(buf, path_);
151
152 buf.clear();
153 std::replace(host_.begin(), host_.end(), ':', ' ');
154 buf.str(host_);
155
156 buf >> host_ >> port_;
157
158 tmp_path_ = path_ + ".download";
159 }
160 };
161
162 // ======================================================================
163
164 SKKAutoUpdateDictionary::SKKAutoUpdateDictionary() : loader_(0) {}
165
166 void SKKAutoUpdateDictionary::Initialize(const std::string& location) {
167 if(loader_.get()) return;
168
169 loader_ = std::auto_ptr<SKKAutoUpdateDictionaryLoader>(new SKKAutoUpdateDictionaryLoader(location));
170 keeper_.Initialize(loader_.get(), 60 * 60 * 6, 3);
171 }
172
173 std::string SKKAutoUpdateDictionary::FindOkuriAri(const std::string& query) {
174 return keeper_.FindOkuriAri(query);
175 }
176
177 std::string SKKAutoUpdateDictionary::FindOkuriNasi(const std::string& query) {
178 return keeper_.FindOkuriNasi(query);
179 }
180
181 bool SKKAutoUpdateDictionary::FindCompletions(const std::string& entry, std::vector<std::string>& result) {
182 return keeper_.FindCompletions(entry, result);
183 }
184
185 // ファクトリメソッドの登録
186 #include "SKKDictionaryFactory.h"
187 static bool initialize = SKKRegisterFactoryMethod<SKKAutoUpdateDictionary>(SKKAutoUpdateDictionaryType);

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26