OSDN Git Service

HTTP GET method is used in ThreadWindow.
authorAiwota Programmer <aiwotaprog@tetteke.tk>
Sat, 27 Jun 2009 09:24:49 +0000 (18:24 +0900)
committerAiwota Programmer <aiwotaprog@tetteke.tk>
Sat, 27 Jun 2009 09:24:49 +0000 (18:24 +0900)
src/bbs_detail_base.cxx
src/bbs_detail_base.hxx
src/text_view_layoutable.cxx
src/text_view_layoutable.hxx
src/thread_window.cxx
src/thread_window.hxx

index 21886ad..0c84ee4 100644 (file)
@@ -91,6 +91,17 @@ std::string Base::get_thread_file_path() const {
   return dir.file_string();
 }
 
+std::string Base::get_thread_idx_path() const {
+  const boost::filesystem::path dir(get_board_idx_dir_path());
+  const boost::filesystem::path xml = dir / (thread_ + ".xml");
+  return xml.file_string();
+}
+
+
+std::string Base::get_thread_dat_uri() const {
+  return "http://" + host_ + "/" + board_ + "/dat/" + thread_ + ".dat";
+}
+
 std::string Base::get_another_thread_uri(const std::string& thread) const {
   return "http://" + host_ + "/test/read.cgi/" + board_ + "/" + thread + "/";
 }
@@ -128,15 +139,17 @@ const std::string& Base::get_bbs_name() const {
   return bbs_name;
 }
 
-void Base::load_thread(text_view::Layoutable& output) const {
-  std::string filepath = get_thread_file_path();
+void Base::load_thread_from_string(const std::string& dat,
+    text_view::Layoutable& output) const {
 
-  std::ifstream ifs(filepath.c_str());
-  int resnum = 1;
+  int resnum = output.get_res_num()+1;
+
+  std::stringstream ss;
+  ss << dat << std::flush;
 
   std::string line;
   Glib::IConv iconv("UTF-8", get_encoding());
-  while (std::getline(ifs, line)) {
+  while (std::getline(ss, line)) {
     dialektos::BufferBuilder builder(output, resnum);
     try {
       dialektos::run_parser<
@@ -151,6 +164,17 @@ void Base::load_thread(text_view::Layoutable& output) const {
     }
     ++resnum;
   }
+
+  output.set_res_num(resnum-1);
+}
+
+void Base::load_thread(text_view::Layoutable& output) const {
+  std::string filepath = get_thread_file_path();
+
+  std::ifstream ifs(filepath.c_str());
+  std::stringstream ss;
+  ss << ifs.rdbuf() << std::flush;
+  load_thread_from_string(ss.str(), output);
 }
 
 void Base::load_subject(std::vector<SubjectItem>& output) const {
@@ -210,6 +234,38 @@ bool Base::operator==(const bbs_detail::Base& rhs) const {
   return host_ == rhs.host_ && board_ == rhs.board_ && thread_ == rhs.thread_;
 }
 
+std::string Base::get_title_from_string(const std::string& dat) const {
+  using namespace boost::xpressive;
+  const sregex regex = bos >> -repeat<4>(*(~_n) >> "<>")
+    >> (s1=*(~_n)) >> _n >> -*_;
+
+  smatch what;
+  if (regex_match(dat, what, regex)) {
+    try {
+      return Glib::convert(what[1], "UTF-8", get_encoding());
+    } catch (const Glib::ConvertError& e) {
+      std::cerr << "convert error!! - " << e.what() << " "
+        << what[1] << std::endl;
+    }
+  }
+  return "";
+}
+
+http::Header Base::get_thread_dat_request_header() const {
+  http::Header request_header;
+  request_header.insert(std::make_pair("Host", host_));
+
+  if (boost::filesystem::exists(get_thread_file_path())) {
+    const size_t file_size = boost::filesystem::file_size(get_thread_file_path());
+    if (file_size > 0) {
+      std::string str = boost::lexical_cast<std::string>(file_size);
+      str = "bytes=" + str + "-";
+      request_header.insert(std::make_pair("Range", str));
+    }
+  }
+  return request_header;
+}
+
 //Base* Base::judge(const std::string& uri) {
 //}
 
index 77563f5..f6e07bd 100644 (file)
@@ -44,16 +44,22 @@ public:
   virtual ~Base();
   virtual std::string get_board_dir_path() const;
   virtual std::string get_thread_file_path() const;
+  virtual std::string get_thread_idx_path() const;
+  virtual std::string get_thread_dat_uri() const;
   virtual std::string get_another_thread_uri(const std::string& thread) const;
   virtual std::string get_board_subject_path() const;
   virtual std::string get_board_subject_uri() const;
   virtual std::string get_board_subject_idx_path() const;
   virtual std::string get_board_idx_dir_path() const;
   virtual http::Header get_board_subject_request_header() const;
+  virtual http::Header get_thread_dat_request_header() const;
+  virtual std::string get_title_from_string(const std::string& dat) const;
 
   virtual const std::string& get_encoding() const;
 
   virtual void load_thread(text_view::Layoutable& output) const;
+  virtual void load_thread_from_string(
+      const std::string& dat, text_view::Layoutable& output) const;
   virtual void load_subject(std::vector<SubjectItem>& output) const;
   virtual void load_subject_from_string(
       const std::string&, std::vector<SubjectItem>& output) const;
index e470293..870c16f 100644 (file)
@@ -37,6 +37,7 @@ Layoutable::Layoutable():
   Scrollable(), pango_layout_(create_pango_layout("")), line_list_(),
       id_map_(new text_element::IDMap),
       res_num_map_(new text_element::ResNumMap),
+      res_num_(0),
       width_(-1) {
 }
 
index cec4a8f..2001ed2 100644 (file)
@@ -57,6 +57,8 @@ public:
   void set_res_num_map(ResNumMapPtrType map) { res_num_map_ = map; }
   IDMapPtrType get_id_map() const { return id_map_; }
   ResNumMapPtrType get_res_num_map() const { return res_num_map_; }
+  void set_res_num(int res_num) { res_num_ = res_num; }
+  int get_res_num() const { return res_num_; }
 protected:
   //virtual bool on_expose_event(GdkEventExpose*);
   virtual bool on_configure_event(GdkEventConfigure*);
@@ -70,6 +72,7 @@ protected:
   LineListType line_list_;
   boost::shared_ptr<text_element::IDMap> id_map_;
   boost::shared_ptr<text_element::ResNumMap> res_num_map_;
+  int res_num_;
   /* cached */
   gint width_;
 };
index 4cabfa3..f767ce7 100644 (file)
 
 #include <glibmm/convert.h>
 #include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/filesystem.hpp>
 #include <iostream>
+#include <fstream>
 #include "bbs_detail_base.hxx"
+#include "thread_idx.hxx"
+#include "http_get.hxx"
 
 
 namespace dialektos {
@@ -37,7 +41,7 @@ ThreadWindow::ThreadWindow(std::auto_ptr<bbs_detail::Base> bbs) :
   SuperClass(),
   text_view_(),
   scrolled_(text_view_.get_adjustment()),
-  bbs_(bbs) {
+  bbs_(bbs), http_getter_(), idx_() {
 
   set_default_size(400,300);
 
@@ -64,6 +68,8 @@ bool ThreadWindow::load() {
 
     std::cout <<
     to_simple_string(microsec_clock::local_time() - start) << std::endl;
+
+    idx_ = ThreadIdx::from_xml(bbs_->get_thread_idx_path());
   }
 
   return false;
@@ -74,5 +80,77 @@ bool ThreadWindow::is_same(const bbs_detail::Base& bbs) const {
   return lhs == bbs;
 }
 
+void ThreadWindow::on_action_view_refresh() {
+  if (http_getter_) return;
+
+  statusbar_.push("HTTP/1.0 GET...");
+
+  const std::string uri = bbs_->get_thread_dat_uri();
+  http::Header request_header = bbs_->get_thread_dat_request_header();
+  if (request_header.find("Range") != request_header.end()) {
+    if (!idx_.last_modified_.empty())
+      request_header.insert(
+          std::make_pair("If-Modified-Since", idx_.last_modified_));
+    if (!idx_.etag_.empty())
+      request_header.insert(std::make_pair("If-None-Match", idx_.etag_));
+  }
+
+  http_getter_.reset(new http::GetInThread(uri, request_header));
+  http_getter_->signal_end().connect(
+      sigc::mem_fun(*this, &ThreadWindow::on_http_get_end));
+  http_getter_->run();
+}
+
+void ThreadWindow::on_http_get_end(bool success) {
+//  const std::string uri = http_getter_->get_uri();
+//  const http::Header request_header = http_getter_->get_request_header();
+  const http::Response response = http_getter_->get_response();
+  http_getter_.reset(0);
+  on_refresh_end(response.get_status_line(), response.get_header());
+
+  const int code = response.get_status_line().get_code();
+  if (code != 200 && code != 206) return;
+
+  bbs_->load_thread_from_string(response.get_content(), text_view_);
+  text_view_.relayout();
+  text_view_.queue_draw();
+
+  save_content(response);
+}
+
+void ThreadWindow::on_refresh_end(const http::StatusLine& status,
+    const http::Header& header) {
+  std::string message = status.get_line();
+  http::Header::const_iterator it = header.find("Last-Modified");
+  if (it != header.end()) {
+    message += " ";
+    message += it->second;
+  }
+  statusbar_.push(message);
+}
+
+void ThreadWindow::save_content(const http::Response& response) {
+  const int code = response.get_status_line().get_code();
+  if (code != 200 && code != 206) return;
+
+  std::ofstream ofs(bbs_->get_thread_file_path().c_str(),
+      code == 200 ?
+          std::ios::out | std::ios::trunc : std::ios::out | std::ios::app);
+  ofs << response.get_content();
+  ofs.close();
+
+  if (code == 200)
+    idx_.title_ = bbs_->get_title_from_string(response.get_content());
+
+  http::Header::const_iterator it = response.get_header().find("Last-Modified");
+  if (it != response.get_header().end()) idx_.last_modified_ = it->second;
+  it = response.get_header().find("ETag");
+  if (it != response.get_header().end()) idx_.etag_ = it->second;
+
+  idx_.line_count_ = text_view_.get_res_num();
+
+  idx_.to_xml(boost::filesystem::path(bbs_->get_thread_idx_path()));
+}
+
 
 } // namespace dialektos
index b39a48f..3489076 100644 (file)
@@ -26,6 +26,8 @@
 #include "application_framework.hxx"
 #include "text_view.hxx"
 #include "scrolled_container.hxx"
+#include "http_get.hxx"
+#include "thread_idx.hxx"
 
 
 namespace dialektos {
@@ -44,12 +46,21 @@ public:
   virtual ~ThreadWindow(){}
 protected:
   ThreadWindow(std::auto_ptr<bbs_detail::Base> bbs);
+
+  virtual void on_action_view_refresh();
 private:
   virtual bool is_same(const bbs_detail::Base& bbs) const;
 
+  void on_http_get_end(bool);
+  void on_refresh_end(const http::StatusLine&, const http::Header&);
+
+  void save_content(const http::Response&);
+
   text_view::TextView text_view_;
   ScrolledContainer scrolled_;
   boost::scoped_ptr<bbs_detail::Base> bbs_;
+  boost::scoped_ptr<http::GetInThread> http_getter_;
+  ThreadIdx idx_;
 };