1 // daemon/Session.cc
2 // This file is part of Anyterm; see http://anyterm.org/
3 // (C) 2005-2006 Philip Endecott
4 
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 
20 #include "Session.hh"
21 
22 #include <sstream>
23 #include <iomanip>
24 
25 #include <unistd.h>
26 #include <signal.h>
27 
28 #include <boost/bind.hpp>
29 
30 #include "Lock.hh"
31 
32 #include "config.hh"
33 #include "html.hh"
34 #include "editscript.hh"
35 #include "Error.hh"
36 #include "Iconver.hh"
37 #include "unicode.hh"
38 
39 
40 using namespace std;
41 using namespace pbe;
42 
43 
Session(int r,int c,int sb,string host,string user,string param,int t,activityfactory_t af,string charset_,bool diff_)44 Session::Session(int r, int c, int sb,
45                  string host, string user, string param,
46                  int t,
47                  activityfactory_t af,
48                  string charset_,
49                  bool diff_):
50   rows(r),
51   cols(c),
52   scrollback(sb),
53   time_out(t),
54   charset(charset_),
55   diff(diff_),
56   utf8_to_charset("UTF-8",charset),
57   charset_to_ucs4(charset,UCS4_NATIVE),
58   ucs4_to_utf8(UCS4_NATIVE,"UTF-8"),
59   screen(rows,cols,scrollback),
60   error(false),
61   term(rows,cols,screen),
62   activity(af(boost::bind(&Session::process_output,this,_1),
63               boost::bind(&Session::process_error,this,_1),
64               host, user, param, r, c))
65 {
66   dirty=true;
67   touch();
68 }
69 
70 
~Session()71 Session::~Session()
72 {}
73 
74 
75 // Timeout unused sessions:
76 
touch(void)77 void Session::touch(void)
78 {
79   last_access = time(NULL);
80 }
81 
82 
83 // Check if session has a backend error to report
84 
report_any_backend_error(void)85 void Session::report_any_backend_error(void)
86 {
87   if (error) {
88     error=false;
89     throw Error(error_msg);
90   }
91 }
92 
93 
94 // Handle Apache requests:
95 
int_to_string(int i)96 string int_to_string(int i)
97 {
98   char b[32];
99   snprintf(b,sizeof(b),"%d",i);
100   return b;
101 }
102 
103 
send(string k)104 void Session::send(string k)
105 {
106   if (!k.empty()) {
107     string dk = utf8_to_charset(k);
108     activity->send(dk);
109   }
110 
111   touch();
112 }
113 
114 
115 
escape_html(string s)116 string escape_html(string s)
117 {
118   string t;
119   for(string::size_type i=0; i<s.length(); i++) {
120     char c=s[i];
121     switch(c) {
122     case '<': t+="&lt;"; break;
123     case '>': t+="&gt;"; break;
124     case '&': t+="&amp;"; break;
125     default:  t+=c; break;
126     }
127   }
128   return t;
129 }
130 
131 
rcv(void)132 string Session::rcv(void)
133 {
134   {
135     Lock<screen_lock_t> l(screen_lock);
136     if (!dirty && !error) {
137       dirty_condition.timed_wait(l,10.0F);
138     }
139   }
140   touch();
141 
142   report_any_backend_error();
143 
144   bool was_dirty;
145   ucs4_string html_screen;
146   {
147     Lock<screen_lock_t> l(screen_lock);
148     was_dirty = dirty;
149     dirty=false;
150     if (!was_dirty) {
151       return "n";
152     }
153     html_screen = htmlify_screen(screen);
154   }
155 
156   string utf8_editscript;
157   if (diff) {
158     ucs4_string editscript = make_editscript(old_html_screen,html_screen);
159     old_html_screen=html_screen;
160     utf8_editscript = ucs4_to_utf8(editscript);
161   } else {
162     utf8_editscript = "R";
163     utf8_editscript.append(ucs4_to_utf8(html_screen));
164   }
165 
166   return utf8_editscript;
167 }
168 
169 
process_output(string s)170 void Session::process_output(string s)
171 {
172   ucs4_string ucs4_s = charset_to_ucs4(s);
173   {
174     Lock<screen_lock_t> l(screen_lock);
175     term.write(ucs4_s);
176     dirty = true;
177   }
178   dirty_condition.notify_all();
179 }
180 
181 
process_error(string s)182 void Session::process_error(string s)
183 {
184   // We could have a lock here, but maybe we can trust that the assignment
185   // to error is atomic.
186   error_msg = s;
187   error = true;
188   dirty_condition.notify_all();
189 }
190 
191 
timed_out(void)192 bool Session::timed_out(void)
193 {
194   return time(NULL) - last_access > time_out;
195 }
196 
197