1 #include "e.h"
2 
3 static Ecore_Con_Url *url_up = NULL;
4 static Eina_List *handlers = NULL;
5 static Ecore_Timer *update_timer = NULL;
6 static E_Dialog *dialog = NULL;
7 static char *machid = NULL;
8 
9 static void
_update_done(void)10 _update_done(void)
11 {
12    if (url_up)
13      {
14         ecore_con_url_free(url_up);
15         url_up = NULL;
16      }
17 }
18 
19 static void
_delete_cb(void * obj EINA_UNUSED)20 _delete_cb(void *obj EINA_UNUSED)
21 {
22    dialog = NULL;
23 }
24 
25 static void
_ok_cb(void * data EINA_UNUSED,E_Dialog * dia EINA_UNUSED)26 _ok_cb(void *data EINA_UNUSED, E_Dialog *dia EINA_UNUSED)
27 {
28    e_object_del(E_OBJECT(dialog));
29    if (e_config->update.later > 0)
30      {
31         e_config->update.later = 0;
32         e_config_save_queue();
33      }
34 }
35 
36 static void
_bother_me_later_cb(void * data EINA_UNUSED,E_Dialog * dia EINA_UNUSED)37 _bother_me_later_cb(void *data EINA_UNUSED, E_Dialog *dia EINA_UNUSED)
38 {
39    e_object_del(E_OBJECT(dialog));
40    // 5 * 5 * 1hr === about 1 day limit, so bother-me later will wait
41    // a day in between botherings. botherings reset on e start or restart
42    if (e_config->update.later < 5)
43      {
44         e_config->update.later++;
45         e_config_save_queue();
46      }
47 }
48 
49 static void
_never_tell_me_cb(void * data EINA_UNUSED,E_Dialog * dia EINA_UNUSED)50 _never_tell_me_cb(void *data EINA_UNUSED, E_Dialog *dia EINA_UNUSED)
51 {
52    if (update_timer) ecore_timer_del(update_timer);
53    update_timer = NULL;
54    e_object_del(E_OBJECT(dialog));
55    e_config->update.check = 0;
56    e_config->update.later = 0;
57    e_config_save_queue();
58 }
59 
60 static void
_new_version(const char * ver)61 _new_version(const char *ver)
62 {
63    char text[2048];
64 
65    if (dialog) return;
66 
67    dialog = e_dialog_new(NULL, "E", "_update_available");
68 
69    e_object_del_attach_func_set(E_OBJECT(dialog), _delete_cb);
70    e_dialog_button_add(dialog, _("OK"), NULL,
71                        _ok_cb, NULL);
72    e_dialog_button_add(dialog, _("Bother me later"), NULL,
73                        _bother_me_later_cb, NULL);
74    e_dialog_button_add(dialog, _("Never tell me"), NULL,
75                        _never_tell_me_cb, NULL);
76    e_dialog_button_focus_num(dialog, 1);
77    e_dialog_title_set(dialog, _("Update Notice"));
78    e_dialog_icon_set(dialog, "dialog-warning", 64);
79 
80    snprintf(text, sizeof(text),
81             _("Your enlightenment version is<ps/>"
82               "not the current latest release.<ps/>"
83               "The latest version is:<ps/>"
84               "<ps/>"
85               "%s<ps/>"
86               "<ps/>"
87               "Please visit www.enlightenment.org<ps/>"
88               "or update your system packages<ps/>"
89               "to get a new version."), ver);
90    e_dialog_text_set(dialog, text);
91    elm_win_center(dialog->win, 1, 1);
92    e_dialog_show(dialog);
93 }
94 
95 static Eina_Bool
_upload_data_cb(void * data EINA_UNUSED,int ev_type EINA_UNUSED,void * event)96 _upload_data_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
97 {
98    Ecore_Con_Event_Url_Data *ev = event;
99    if (ev->url_con != url_up) return EINA_TRUE;
100    if (ev->size > 0)
101      {
102         char *txt = alloca(ev->size + 1);
103 
104         memcpy(txt, ev->data, ev->size);
105         txt[ev->size] = 0;
106 
107         if (!strncmp(txt, "OK", 2))
108           {
109           }
110         else if (!strncmp(txt, "OLD", 3))
111           {
112              char *ver = strchr(txt, ' ');
113              if (ver)
114                {
115                   ver++;
116                   _new_version(ver);
117                }
118           }
119      }
120    return EINA_FALSE;
121 }
122 
123 static Eina_Bool
_upload_progress_cb(void * data EINA_UNUSED,int ev_type EINA_UNUSED,void * event)124 _upload_progress_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
125 {
126    Ecore_Con_Event_Url_Progress *ev = event;
127    if (ev->url_con != url_up) return EINA_TRUE;
128    return EINA_FALSE;
129 }
130 
131 static Eina_Bool
_upload_complete_cb(void * data EINA_UNUSED,int ev_type EINA_UNUSED,void * event)132 _upload_complete_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
133 {
134    Ecore_Con_Event_Url_Complete *ev = event;
135    if (ev->url_con != url_up) return EINA_TRUE;
136    if (ev->status != 200)
137      {
138         _update_done();
139         return EINA_FALSE;
140      }
141    _update_done();
142    return EINA_FALSE;
143 }
144 
145 static void
_update_machid_get(void)146 _update_machid_get(void)
147 {
148    FILE *f;
149    char buf[4096], *c;
150    size_t len;
151 
152    f = fopen("/etc/machine-id", "r");
153    if (!f) f = fopen("/var/lib/dbus/machine-id", "r");
154    if (!f)
155      {
156         e_user_dir_concat_static(buf, ".machid");
157         f = fopen(buf, "r");
158      }
159    if (f)
160      {
161         len = fread(buf, 1, sizeof(buf) - 1, f);
162         if (len > 10)
163           {
164              buf[len] = 0;
165              for (c = buf; *c; c++)
166                {
167                   if (!isalnum(*c))
168                     {
169                        *c = 0;
170                        break;
171                     }
172                }
173              machid = strdup(buf);
174              fclose(f);
175              return;
176           }
177         fclose(f);
178      }
179 
180    // generate ID
181    e_user_dir_concat_static(buf, ".machid");
182    f = fopen(buf, "w");
183    if (f)
184      {
185         double t;
186         fwrite("GEN-", 4, 1, f);
187         t = ecore_time_unix_get();
188         fprintf(f, "%1.16f-%i-%i\n", t, rand(), rand());
189         fclose(f);
190         _update_machid_get();
191         return;
192      }
193    // this just is all a wash - just use this
194    machid = strdup("NOIDEAWHATTHEIDOFTHISMACHINEIS");
195 }
196 
197 static void
_update_post_generate(char * buf,int size)198 _update_post_generate(char *buf, int size)
199 {
200    if (!machid) _update_machid_get();
201    if (!machid) return;
202    snprintf(buf, size,
203             "CLIENT %s\n"
204             "UPDATE enlightenment %s",
205             machid, VERSION);
206 }
207 
208 static void
_update_check(void)209 _update_check(void)
210 {
211    char buf[1024];
212 
213    if (url_up) _update_done();
214    url_up = ecore_con_url_new("http://www.enlightenment.org/update.php");
215    if (url_up)
216      {
217         _update_post_generate(buf, sizeof(buf));
218         ecore_con_url_http_version_set(url_up, ECORE_CON_URL_HTTP_VERSION_1_0);
219         ecore_con_url_post(url_up, buf, strlen(buf), "text/plain");
220      }
221    else
222      _update_done();
223 }
224 
225 static Eina_Bool
_update_timeout_cb(void * data)226 _update_timeout_cb(void *data)
227 {
228    double t = 3600.0; // base minimum betwene checks -> 1hr min
229    int later = e_config->update.later;
230 
231    if (e_config->update.check) _update_check();
232    if (update_timer) ecore_timer_del(update_timer);
233    if (later > 0)
234      {
235         later++;
236         t *= (later * later);
237      }
238    update_timer = ecore_timer_loop_add(t, _update_timeout_cb, data);
239    return EINA_FALSE;
240 }
241 
242 EINTERN int
e_update_init(void)243 e_update_init(void)
244 {
245    if (ecore_con_url_init())
246      {
247         handlers = eina_list_append
248             (handlers, ecore_event_handler_add
249               (ECORE_CON_EVENT_URL_DATA, _upload_data_cb, NULL));
250         handlers = eina_list_append
251             (handlers, ecore_event_handler_add
252               (ECORE_CON_EVENT_URL_PROGRESS, _upload_progress_cb, NULL));
253         handlers = eina_list_append
254             (handlers, ecore_event_handler_add
255               (ECORE_CON_EVENT_URL_COMPLETE, _upload_complete_cb, NULL));
256         if (e_config->update.check)
257           {
258              e_config->update.check = 0;
259              _update_timeout_cb(NULL);
260              e_config->update.check = 1;
261           }
262      }
263    return 1;
264 }
265 
266 EINTERN int
e_update_shutdown(void)267 e_update_shutdown(void)
268 {
269    if (handlers)
270      {
271         _update_done();
272         ecore_con_url_shutdown();
273      }
274    if (update_timer)
275      {
276         ecore_timer_del(update_timer);
277         update_timer = NULL;
278      }
279    if (dialog) e_object_del(E_OBJECT(dialog));
280    dialog = NULL;
281    _update_done();
282    if (machid)
283      {
284         free(machid);
285         machid = NULL;
286      }
287    return 1;
288 }
289 
290