1 /*
2  * Copyright 2011 kubtek <kubtek@mail.com>
3  *
4  * This file is part of StarDict.
5  *
6  * StarDict is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * StarDict is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with StarDict.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef _STARDICT_CLIENT_HPP_
21 #define _STARDICT_CLIENT_HPP_
22 
23 #include <glib.h>
24 #include <list>
25 #include <vector>
26 
27 #ifndef _WIN32
28 #  include <netdb.h>
29 #else
30 typedef unsigned long in_addr_t;
31 #endif
32 
33 #include "stardict-sigc++.h"
34 
35 
36 namespace STARDICT {
37 	enum {
38 		CMD_CLIENT,
39 		CMD_AUTH,
40 		CMD_LOOKUP,
41 		CMD_PREVIOUS,
42 		CMD_NEXT,
43 		//CMD_QUERY,
44 		CMD_SELECT_QUERY,
45 		CMD_SMART_QUERY,
46 		CMD_DEFINE,
47 		CMD_REGISTER,
48 		//CMD_CHANGE_PASSWD,
49 		CMD_SET_DICT_MASK,
50 		CMD_GET_DICT_MASK,
51 		//CMD_SET_COLLATE_FUNC,
52 		//CMD_GET_COLLATE_FUNC,
53 		//CMD_SET_LANGUAGE,
54 		//CMD_GET_LANGUAGE,
55 		//CMD_SET_EMAIL,
56 		//CMD_GET_EMAIL,
57 		CMD_MAX_DICT_COUNT,
58 		CMD_DIR_INFO,
59 		CMD_DICT_INFO,
60 		//CMD_USER_LEVEL,
61 		//CMD_GET_USER_LEVEL,
62 		CMD_GET_ADINFO,
63 		CMD_QUIT,
64 	};
65 	struct LookupResponse {
66 		struct DictResponse {
67 			DictResponse();
68 			~DictResponse();
69 			char *oword;
70 			struct DictResult {
71 				DictResult();
72 				~DictResult();
73 				char *bookname;
74 				struct WordResult {
75 					WordResult();
76 					~WordResult();
77 					char *word;
78 					std::list<char *> datalist;
79 				};
80 				std::list<struct WordResult *> word_result_list;
81 			};
82 			std::list<struct DictResult *> dict_result_list;
83 		};
84 		~LookupResponse();
85 		struct DictResponse dict_response;
86 		enum ListType {
87 			ListType_None,
88 			ListType_List,
89 			ListType_Rule_List,
90 			ListType_Regex_List,
91 			ListType_Fuzzy_List,
92 			ListType_Tree,
93 		};
94 		ListType listtype;
95 		struct WordTreeElement {
96 			char *bookname;
97 			std::list<char *> wordlist;
98 		};
99 		union {
100 			std::list<char *> *wordlist;
101 			std::list<WordTreeElement *> *wordtree;
102 		};
103 	};
104 	class Cmd {
105 	public:
106 		int command;
107 		struct AuthInfo {
108 			std::string user;
109 			std::string passwd;
110 		};
111 		union {
112 			char *data;
113 			AuthInfo *auth;
114 		};
115 		int reading_status;
116 		unsigned int seq;
117 		union {
118 			struct LookupResponse *lookup_response;
119 			std::list<char *> *wordlist_response;
120 		};
121 		Cmd(int cmd, ...);
122 		~Cmd();
123 	private:
124 		static unsigned int next_seq;
125 	};
126 };
127 
128 class StarDictCache {
129 public:
130 	StarDictCache();
131 	~StarDictCache();
132 	char *get_cache_str(const char *key);
133 	void save_cache_str(const char *key, char *str);
134 	void clean_cache_str(const char *key);
135 	STARDICT::LookupResponse *get_cache_lookup_response(const char *key);
136 	void save_cache_lookup_response(const char *key, STARDICT::LookupResponse *lookup_response);
137 	void clean_cache_lookup_response();
138 	void clean_all_cache();
139 private:
140 	static const unsigned int str_pool_size = 30;
141 	size_t cur_str_pool_pos;
142 	struct StrElement {
143 		std::string key;
144 		char *data;
145 	};
146 	std::vector<StrElement *> str_pool;
147 
148 	static const unsigned int lookup_response_pool_size = 60;
149 	size_t cur_lookup_response_pool_pos;
150 	struct LookupResponseElement {
151 		std::string key;
152 		struct STARDICT::LookupResponse *lookup_response;
153 	};
154 	std::vector<LookupResponseElement *> lookup_response_pool;
155 };
156 
157 class StarDictClient : private StarDictCache {
158 public:
159 	static sigc::signal<void, const char *> on_error_;
160 	static sigc::signal<void, const struct STARDICT::LookupResponse *, unsigned int> on_lookup_end_;
161 	static sigc::signal<void, const struct STARDICT::LookupResponse *, unsigned int> on_floatwin_lookup_end_;
162 	static sigc::signal<void, const char *> on_register_end_;
163 	static sigc::signal<void, const char *> on_getdictmask_end_;
164 	static sigc::signal<void, const char *> on_getadinfo_end_;
165 	static sigc::signal<void, const char *> on_dirinfo_end_;
166 	static sigc::signal<void, const char *> on_dictinfo_end_;
167 	static sigc::signal<void, int> on_maxdictcount_end_;
168 	static sigc::signal<void, std::list<char *> *> on_previous_end_;
169 	static sigc::signal<void, std::list<char *> *> on_next_end_;
170 
171 	StarDictClient();
172 	~StarDictClient();
173 
174 	void set_server(const char *host, int port = 2628);
175 	void set_auth(const char *user, const char *md5passwd);
176 	bool try_cache(STARDICT::Cmd *c);
177 	void send_commands(int num, ...);
178 	void try_cache_or_send_commands(int num, ...);
179 private:
180 	int sd_;
181 	GIOChannel *channel_;
182 	guint in_source_id_;
183 	guint out_source_id_;
184 	std::string host_;
185 	int port_;
186 	bool host_resolved;
187 	in_addr_t sa;
188 	std::string user_;
189 	std::string md5passwd_;
190 	bool is_connected_;
191 	bool waiting_banner_;
192 	std::list<STARDICT::Cmd *> cmdlist;
193 	struct reply {
194 		std::string daemonStamp;
195 	} cmd_reply;
196 	enum ReadType {
197 		READ_LINE,
198 		READ_STRING,
199 		READ_SIZE,
200 	} reading_type_;
201 	char *size_data;
202 	gsize size_count;
203 	gsize size_left;
204 
205 	void clean_command();
206 	void request_command();
207 	void disconnect();
208 	static gboolean on_io_in_event(GIOChannel *, GIOCondition, gpointer);
209 	static gboolean on_io_out_event(GIOChannel *, GIOCondition, gpointer);
210 	void connect();
211 	static void on_resolved(gpointer data, bool resolved, in_addr_t sa);
212 	static void on_connected(gpointer data, bool succeeded);
213 	void write_str(const char *str, GError **err);
214 	bool parse(gchar *line);
215 	int parse_banner(gchar *line);
216 	int parse_command_client(gchar *line);
217 	int parse_command_auth(gchar *line);
218 	int parse_command_register(gchar *line);
219 	int parse_command_setdictmask(gchar *line);
220 	int parse_command_getdictmask(STARDICT::Cmd* cmd, gchar *line);
221 	int parse_command_getadinfo(STARDICT::Cmd* cmd, gchar *line);
222 	int parse_command_dirinfo(STARDICT::Cmd* cmd, gchar *line);
223 	int parse_command_dictinfo(STARDICT::Cmd* cmd, gchar *line);
224 	int parse_command_maxdictcount(STARDICT::Cmd* cmd, gchar *line);
225 	int parse_command_quit(gchar *line);
226 	int parse_dict_result(STARDICT::Cmd* cmd, gchar *buf);
227 	int parse_wordlist(STARDICT::Cmd* cmd, gchar *buf);
228 };
229 
230 #endif
231