/* This file is part of Bolixo. Bolixo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bolixo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bolixo. If not, see . */ #include #include #include #include #include #include #include #include #include #define DEFINE_TBFTYPE #include "../bolixo.h" #define DEFINE_USERINFO #include "util.h" #include #include "../bolixo.m" #include "../helper.h" #define INSTRUMENT_EXTERN #include "../instrument.h" #include "w_var.h" #include "steps.h" using namespace std; USERLOGINFO userinfo; string w_session; #define bo_sessiond_client_test_NOTNEED #define bo_sessiond_client_getsessioninfovars_NOTNEED #define bod_client_createsession_NOTNEED #define bod_client_login_NOTNEED #define bod_client_logout_NOTNEED #define bod_client_adduser_NOTNEED #define bod_client_confirmuser_NOTNEED #define bod_client_deleteuser_NOTNEED #define bod_client_confirmdelete_NOTNEED #define bod_client_addfile_NOTNEED #define bod_client_addfile_bob_NOTNEED #define bod_client_appendfile_NOTNEED #define bod_client_delfile_NOTNEED #define bod_client_undelete_NOTNEED #define bod_client_modifyfile_NOTNEED #define bod_client_modifyfile_bob_NOTNEED #define bod_client_rename_NOTNEED #define bod_client_copy_NOTNEED #define bod_client_readfile_NOTNEED #define bod_client_mkdir_NOTNEED #define bod_client_rmdir_NOTNEED #define bod_client_listdir_NOTNEED #define bod_client_set_access_NOTNEED #define bod_client_create_group_list_NOTNEED #define bod_client_create_group_NOTNEED #define bod_client_set_group_NOTNEED #define bod_client_set_member_NOTNEED #define bod_client_delete_list_NOTNEED #define bod_client_delete_group_NOTNEED #define bod_client_list_lists_NOTNEED #define bod_client_list_groups_NOTNEED #define bod_client_list_inboxes_NOTNEED #define bod_client_list_msgs_NOTNEED #define bod_client_sendmsg_NOTNEED #define bod_client_sendmsg_project_NOTNEED #define bod_client_replymsg_NOTNEED #define bod_client_replymsg_project_NOTNEED #define bod_client_sendattach_NOTNEED #define bod_client_create_project_dir_NOTNEED #define bod_client_verifysign_NOTNEED #define bod_client_sendtalk_NOTNEED #define bod_client_list_talk_NOTNEED #define bod_client_contact_list_NOTNEED #define bod_client_public_checkuser_NOTNEED #define bod_client_public_listdir_NOTNEED #define bod_client_public_list_talk_NOTNEED #define bod_client_config_write_NOTNEED #define bod_client_config_read_NOTNEED #define bod_client_contact_manage_NOTNEED #define bod_client_contact_request_NOTNEED #define bod_client_sendtalk_file_NOTNEED #define bod_client_set_group_desc_NOTNEED #define bod_client_set_list_desc_NOTNEED #define bod_client_form_readvar_NOTNEED #define bod_client_form_savevar_NOTNEED #define bod_client_form_deletevar_NOTNEED #define bod_client_form_deleteall_NOTNEED #define bod_client_interest_set_NOTNEED #define bod_client_interest_unset_NOTNEED #define bod_client_interest_list_NOTNEED #define bod_client_interest_check_NOTNEED #define bod_client_info_read_NOTNEED #define bod_client_info_write_NOTNEED #define bod_client_systempubkey_NOTNEED #define bod_client_systemsign_NOTNEED #define bod_client_registernode_NOTNEED #define bod_client_getpubkey_NOTNEED #define bod_client_remotelogin_NOTNEED #define bod_client_remotepass_NOTNEED #define bod_client_nodelogin_NOTNEED #define bod_client_nodepass_NOTNEED #define bod_client_remote_interest_set_NOTNEED #define bod_client_remote_interest_unset_NOTNEED #define bod_client_sendtalk_anon_NOTNEED #define bod_client_list_contacts_NOTNEED #define bod_client_get_notification_NOTNEED #define bod_client_set_notification_NOTNEED #include "../proto/bod_client.protoch" #define bo_sessiond_client_getsessioninfo_NOTNEED #define bo_sessiond_client_setvar_NOTNEED #include "../proto/bo-sessiond_client.protoch" W_UNSIGNED w_robot ("robot"); static W_SSTRING w_file("file"); static float small_size=0.9; static unsigned draw_tab_height() { unsigned fontsize = tlmpweb_fontsize(); unsigned height = fontsize*1.3*small_size; if (height < 20) height = 20; return height+2; // Keep some space at the top } unsigned draw_tab ( unsigned width, // TAB width or 0 (computed from the title) const char *fill, // Fill color const char *fill_in, // Fill color for mouseover bool close, // Close the path or not const char *title, bool drawx, // Put an X at the end (normally to close the TAB) PARAM_STRING href, // URL when the TAB is clicked PARAM_STRING xref) // URL when the X is clicked { unsigned height = draw_tab_height(); static STATIC_ID alloc_id; unsigned id = alloc_id++; if (width == 0){ width = tlmpweb_displaylen(title,small_size); // See the .small css entry above if (drawx){ width += 10+5+15; }else{ // We put 10 pixels on each side width += 10+10; } } htmlprintf ("\n",width,height); htmlprintf ("\n"); if (drawx && !tlmpweb_ismobile()){ unsigned x=width-17; htmlprintf ("\n",xref.ptr,id,id); // First rect is there to make the a tag larger. fill=none does not work. So we have to give it the same color // as the tab and changefill2 will change the color of the tab and this rect. // The second rect is used to highlit the X htmlprintf ("\n",id,x-5,4,height-6,fill); unsigned hmiddle = height/2+2; unsigned h14 = height-8; unsigned h8=height/3; if (h8 & 1) h8++; // Make sure h8 is even. htmlprintf ("\n",id,x-3,4,h14,height-4); htmlprintf ("\n" ,x,hmiddle-h8/2,h8,h8 ,x,hmiddle+h8/2,h8,h8); htmlout ("\n"); } htmlout ("\n"); return width; } // Same thing with no X unsigned draw_tab (unsigned width, const char *fill, const char *fill_in, bool close, const char *title, PARAM_STRING href) { return draw_tab (width,fill,fill_in,close,title,false,href,""); } void draw_left_arrow(bool visible, PARAM_STRING xref) { unsigned height = draw_tab_height(); htmlprintf ("\n",height); if (visible){ static STATIC_ID alloc_id; unsigned id=alloc_id++; htmlprintf ("\n",xref.ptr,id,id); htmlprintf ("\n",id,height-4); } const char *color = visible ? "black" : "white"; unsigned h2=height/2; htmlprintf ("\n",color,color,h2,h2-8,h2+8); if (visible) htmlout ("\n"); // Always put the underline htmlprintf ("\n",height); htmlout ("\n"); } void draw_right_arrow(bool visible, PARAM_STRING xref) { unsigned height = draw_tab_height(); htmlprintf ("\n",height); if (visible){ static STATIC_ID alloc_id; unsigned id=alloc_id++; htmlprintf ("\n",xref.ptr,id,id); htmlprintf ("\n",id,height-4); } const char *color = visible ? "black" : "white"; unsigned h2=height/2; htmlprintf ("\n",color,color,h2,h2-8,h2+8); if (visible) htmlout ("\n"); // Always put the underline htmlprintf("\n",height); htmlout ("\n"); } static void print_href_c (const char *title, PARAM_STRING href, const char *color) { bool close = strcmp(color,"white")==0 ? false : true; draw_tab (0,color,color,close,title,href); } void print_href (const char *title, PARAM_STRING href, bool notify) { print_href_c(title, href,notify ? "pink" : "#EAEAEA"); } void print_aref (const char *page, const char *title, int step, bool notify) { string href = string_f ("%s?webstep=%d",page,step); print_href (title,href,notify); } void print_aref (const char *title, int step, bool notify) { print_aref (tlmpweb_curpage(),title,step,notify); } void print_aref_selected (const char *page, const char *title, int step) { string href = string_f ("%s?webstep=%d",page,step); print_href_c (title,href,"white"); } void print_aref_selected (const char *title, int step) { print_aref_selected (tlmpweb_curpage(),title,step); } #if 0 void print_aref_selected (const char *page, const char *title, int step, W_VAR &var) { SSTRING val; var.getvalstr(val); string href = string_f ("%s?webstep=%d&%s=%s",page,step,var.getname(),val.c_str()); print_href_c (title,href,"#220022"); } void print_aref_selected (const char *title, int step, W_VAR &var) { print_aref_selected (tlmpweb_curpage(),title,step,var); } void print_aref (const char *page, const char *title, int step, W_VAR &var) { SSTRING val; var.getvalstr(val); string href = string_f ("%s?webstep=%d&%s=%s",page,step,var.getname(),val.c_str()); print_href (title,href); } void print_aref (const char *title, int step, W_VAR &var) { print_aref (tlmpweb_curpage(),title,step,var); } void print_aref (const char *title, int step, W_VAR &var1, W_VAR &var2) { SSTRING val1,val2; var1.getvalstr(val1); var2.getvalstr(val2); string href = string_f ("%s?webstep=%d&%s=%s&%s=%s",tlmpweb_curpage(),step ,var1.getname(),val1.c_str() ,var2.getname(),val2.c_str()); print_href (title,href); } void print_aref (const char *title, int step, W_VAR &var1, const char *varname2, const char *val2) { SSTRING val1; var1.getvalstr(val1); string href = string_f ("%s?webstep=%d&%s=%s&%s=%s",tlmpweb_curpage(),step ,var1.getname(),val1.c_str() ,varname2,val2); print_href (title,href); } void print_aref (const char *title, int step, W_VAR &var1, W_VAR &var2, W_VAR &var3) { SSTRING val1,val2,val3; var1.getvalstr(val1); var2.getvalstr(val2); var3.getvalstr(val3); string href = string_f ("%s?webstep=%d&%s=%s&%s=%s&%s=%s",tlmpweb_curpage(),step ,var1.getname(),val1.c_str() ,var2.getname(),val2.c_str() ,var3.getname(),val3.c_str()); print_href (title,href); } #endif const char *format_line (const char *s) { while (*s != '\0' && *s != '\n'){ char car = *s++; if (car == '<'){ htmlout ("<"); }else if (car == '>'){ htmlout (">"); }else{ htmlout (car); } } return s; } const char *format_url (const char *s) { if (strncmp(s,"http://",7)!=0 && strncasecmp(s,"https://",8)!=0) htmlout ("http://"); return format_line (s); } void format_href(const char *s) { htmlout (""); if (strlen(s) > 50){ string tmp = string(s,80) + "..."; format_url(tmp.c_str()); }else{ format_url(s); } htmlout(""); } void format_content (const char *s, int nbline, bool &more) { more = false; bool ol_on = false; bool ul_on = false; bool quote_on = false; int noline = 0; while (*s != '\0' && noline < nbline){ if (*s == '\n'){ if (ul_on){ htmlout (""); ul_on = false; }else if (ol_on){ htmlout (""); ol_on = false; }else if (quote_on){ htmlout (""); quote_on = false; } htmlout ("

\n"); s++; noline++; }else{ const char *closing = ""; if (*s == '*'){ if (ol_on){ ol_on = false; htmlout (""); } if (!ul_on){ htmlout ("

    "); ul_on = true; } htmlout ("
  • "); s++; }else if (*s == '#'){ if (ul_on){ htmlout ("
"); ul_on = false; } if (!ol_on){ htmlout ("
    "); ol_on = true; } htmlout ("
  1. "); s++; }else if (*s == '?'){ s++; while (*s == ' ') s++; htmlout (""); s = format_url (s); htmlout (""); }else if (*s == '!'){ s++; if (*s == '!'){ s++; htmlout ("

    "); closing = "

    "; }else{ htmlout (""); closing = ""; } }else if (*s == '>'){ quote_on=true; s++; htmlout ("
    "); } s = format_line (s); noline++; htmlout (closing); if (*s == '\n'){ s++; htmlout ('\n'); } } } if (ul_on){ htmlout (""); } if (ol_on){ htmlout ("
"); } if (*s != '\0') more = true; } void format_content (const char *s) { bool more; format_content(s,10000,more); } void formatting_tips() { printhref ("/marker.html","Formatting tips",false); } void util_google_code() { #if 0 htmlout ("\n"); htmlout ("\n"); #endif } static unsigned mobile_body_font_size=300; static unsigned mobile_input_font_size=80; void util_setmobilespecs (unsigned body_font_size, unsigned input_font_size) { mobile_body_font_size = body_font_size; mobile_input_font_size = input_font_size; } /* Javascript needed at the end of the HTML */ void util_endscript(PARAM_STRING urlparam) { // Script to make sure the webtabs tabs use the full height of the screen // Then it takes the webtables and grows them too. document.onreadystatechange = function () { var state = document.readyState; if (state == 'interactive') { fixsize(); } else if (state == 'complete') { } }; var diff = 0; function allDescendants (node,total) { //console.log ('Enter ' + node.className + ' ' + node.id); if (node.className == "tabs" || node.className == "subtabs"){ var bord=(node.offsetHeight-node.clientHeight); //var style = node.currentStyle || window.getComputedStyle(node); var style = window.getComputedStyle(node); var margins = parseInt(style.marginTop,10) + parseInt(style.marginBottom,10); var paddings = parseInt(style.paddingTop,10) + parseInt(style.paddingBottom,10); total += bord + margins + paddings; console.log ("border cls=" + node.className + " node.id=" + node.id + " total="+total+" bord="+bord + " margins="+margins+ " paddings="+paddings); if (node.className == "subtabs"){ console.log ("Set subtabs "+node.id+" total="+total+" oldheight="+node.offsetHeight); node.style.height = diff - total; } } for (var i = 0; i < node.childNodes.length; i++) { var child = node.childNodes[i]; if (child.id != null && (child.id == "tabs" || child.id == "tab_form" || child.id == "webtable-top")){ total += child.offsetHeight; var style = window.getComputedStyle(child); total += parseInt(style.getPropertyValue('margin-top')); total += parseInt(style.getPropertyValue('margin-bottom')); if (child.id == "tab_form") total += 2; // Bug scrollbar ??? console.log ("child.id=" + child.id + " total="+total+" height="+child.offsetHeight); }else{ if (child.id != null && child.id == "vframe2h"){ var bord=(child.offsetWidth-child.clientWidth); total += bord; console.log ("border child.id=" + child.id + " total="+total+" border="+bord); }else if (child.className == "webtable" || child.className == "textgrow"){ console.log ("Set webtable "+child.id+" total="+total+" oldheight="+child.offsetHeight); child.style.height = diff - total; break; } total = allDescendants(child,total); } } return total; } function fixsize(){ var t = document.getElementById('head').offsetHeight; diff = window.innerHeight-t; console.log ("diff="+diff); document.getElementById('body').style.height = diff-1; document.getElementById('main').style.height = window.innerHeight-1; var tabs = document.getElementsByClassName("tabs"); for (var i=0; i webtable_setscroll(); if (tlmpweb_some_geometry_missing()){ const char *sep1 = "?"; const char *sep2 = "&"; if (urlparam.ptr[0] == '\0'){ sep1 = sep2 = ""; } htmlprintf ("formsubmit(\"%s%s%s\");\n",tlmpweb_curpage(),sep1,urlparam.ptr); } ?> } void util_defstyles() { unsigned body_font_size=100; unsigned input_font_size=100; unsigned input_checkbox=1; if (tlmpweb_ismobile()){ body_font_size = mobile_body_font_size; input_font_size = mobile_input_font_size; small_size = 1.0; input_checkbox = 3; } htmlout ("\n"); htmlout ("\n"); tlmpweb_setscripts(); htmlout ("\n"); } /* Draw a 3 dots menu and the associated popup. */ void util_dotmenu (const vector &menu, bool is_active) { static const char *id_dropdown = "dropdown-dot"; static const char *id_menu = "dotmenu"; unsigned popup_width = 0; { DIV d("dropdown"); d.print(); DIV dd("dropdown-content",id_dropdown); dd.print(); for (auto &m:menu){ htmlprintf ("%s\n",tlmpweb_curpage(),m.step,m.menu); unsigned menu_width = tlmpweb_displaylen(m.menu); if (menu_width > popup_width) popup_width = menu_width; } } DIV d; d.id(id_menu).print(); unsigned height = draw_tab_height(); unsigned width = height; if (tlmpweb_ismobile()) width *= 2; unsigned w2 = width/2; unsigned ray=tlmpweb_ismobile() ? 2 : 1; htmlprintf ("",id_dropdown,id_menu,popup_width); htmlprintf ("",width,height); htmlprintf ("",w2,height/4,ray); htmlprintf ("",w2,height/2,ray); htmlprintf ("",w2,height*3/4,ray); if (!is_active) htmlprintf ("",height,width); htmlout (""); htmlout ("\n"); } void printhref(const char *url, const char *text) { htmlprintf ("
 %s 
",url,text); } void printhref_selected(const char *url, const char *text) { htmlprintf ("
 %s 
",url,text); } void printhref(const char *url, const char *text, bool largewindow) { if (w_robot){ htmlprintf ("%s",url,text); }else{ const char *script = largewindow ? "popup_large" : "popup_small"; htmlprintf ("
 %s 
",script,url,text); } } void printhref_raw(const char *url, const char *text, bool largewindow) { if (w_robot){ htmlprintf ("%s",url,text); }else{ const char *script = largewindow ? "popup_large" : "popup_small"; htmlprintf ("%s",script,url,text); } } string format_date (unsigned format, PARAM_STRING pdate) { static TRANS_NOTLOAD *tbmonth[]={P_MSG_U(I_JANUARY,"Jan"),P_MSG_U(I_FEBRUARY,"Feb"),P_MSG_U(I_MARCH,"Mar") ,P_MSG_U(I_APRIL,"Apr"),P_MSG_U(I_MAY,"May"),P_MSG_U(I_JUNE,"Jun") ,P_MSG_U(I_JULY,"Jul"),P_MSG_U(I_AUGUST,"Aug"),P_MSG_U(I_SEPTEMBER,"Sep") ,P_MSG_U(I_OCTOBER,"Oct"),P_MSG_U(I_NOVEMBER,"Nov"),P_MSG_U(I_DECEMBER,"Dec")}; const char *date = pdate.ptr; if (format != 0){ return date; }else if (strlen(date)==19){ int year = atoi(date); int month = atoi(date+5); int day = atoi(date+8); int hour = atoi(date+11); int minu = atoi(date+14); const char *ampm = "AM"; if (hour > 12){ hour -= 12; ampm="PM"; } return string_f (" %s %d %04d @%d:%02d%s",tbmonth[month-1]->get(),day,year,hour,minu,ampm); }else if (strlen(date)==10){ int year = atoi(date); int month = atoi(date+5); int day = atoi(date+8); return string_f (" %s %d %04d",tbmonth[month-1]->get(),day,year); }else{ return date; } } string format_time (unsigned format, PARAM_STRING ptime) { const char *time = ptime.ptr; if (format != 0){ return string(time,5); }else if (strlen(time)==8){ int hour = atoi(time); int minu = atoi(time+3); const char *ampm = "AM"; if (hour > 12){ hour -= 12; ampm="PM"; } return string_f ("%d:%02d%s",hour,minu,ampm); }else{ return time; } } void util_formanchor() { htmlprintf ("\n"); } void button_row(_F_button_row &c, int border, const char *bgcolor, bool alignleft) { vector left_lines; tlmpweb_pushgrab(left_lines); c.align="left"; c.draw(); tlmpweb_popgrab(); vector right_lines; tlmpweb_pushgrab(right_lines); c.align="right"; c.spliton = false; c.draw_right(); tlmpweb_popgrab(); if (left_lines.size() > 0 || right_lines.size()>0){ DIV cols; cols.dispflex().flowrow(); if (!alignleft) cols.sfloat("right"); cols.print(); if (c.href_arrow_left.size() > 0){ DIV col; col.flexfixe().print(); draw_left_arrow(c.arrow_left_visible,c.href_arrow_left); } { DIV col; col.flexgrow().overflow("hidden").print(); DIV d; d.dispflex().flowrow().bg("none").overflow("hidden").print(); if (left_lines.size() > 0){ htmlout (left_lines); htmlout ("\n"); } if (c.endline){ htmlout ("
\n"); unsigned height = draw_tab_height(); htmlprintf ("\n",c.endline_width,height); htmlprintf ("\n",height,c.endline_width); htmlout ("\n"); htmlout ("
\n"); } } if (c.href_arrow_right.size() > 0){ DIV col; col.flexfixe().print(); draw_right_arrow(c.arrow_right_visible,c.href_arrow_right); } DIV end; end.flexfixe().print(); if (right_lines.size() > 0){ htmlout (right_lines); htmlout ("\n"); } } } void button_row(_F_button_row &c, int border, const char *bgcolor) { button_row(c,border,bgcolor,true); } void button_row(_F_button_row &c, int border) { button_row (c,border,"white",true); } void button_row(_F_button_row &c) { button_row(c,0,"white",true); } void _F_button_row::draw_right() { } void _F_button_row::reset() { spliton = false; tlmpweb_resetgrab(); } void _F_button_row::split() { if (spliton) htmlout ("\n"); htmlout ("
\n"); spliton = true; } void _F_button_row::drawendline(unsigned width) { endline_width = width; endline = true; } void _F_button_row::drawleftarrow (PARAM_STRING href, bool visible) { arrow_left_visible = visible; href_arrow_left = href.ptr; } void _F_button_row::drawrightarrow (PARAM_STRING href, bool visible) { arrow_right_visible = visible; href_arrow_right = href.ptr; } static const char *tbtype[]={ "text/html", //FILE_UNKNOWN, "text/html", //FILE_TEXT, "audio/mp3", //FILE_SOUND_MP3, "audio/ogg", //FILE_SOUND_OGG, "image/jpeg", //FILE_IMAGE_JPG, "image/png", //FILE_IMAGE_PNG, "image/gig", //FILE_IMAGE_GIF, "video/mpeg" //FILE_VIDEO, }; static void util_sendfile_common(CONNECT_INFO &con, const READINFO_receive &info, const BOB_TYPE &content, bool more, const char *handle, const char *session) { glocal CONNECT_INFO *con = &con; tlmpweb_setmodified(info.modified); tlmpweb_setexpire(time(NULL)+365*24*60*60); // Expires in one year tlmpweb_doctype (tbtype[info.file_type],info.size); htmlwrite (content.getbuffer(),content.getsize()); glocal bool more = more; while (glocal.more){ (*glocal.con,session,handle); htmlwrite (content.getbuffer(),content.getsize()); glocal.more = more; //tlmp_error ("readmore success=%d msg=%s\n",success,msg); } } static int util_sendfile (const char *fname) { int ret = -1; FILE *fin = fopen (fname,"r"); if (fin != NULL){ struct stat64 st; time_t mod = 0; unsigned size = 0; if (fstat64(fileno(fin),&st)!=-1){ size = st.st_size; mod = st.st_mtime; } tlmpweb_setmodified(mod); tlmpweb_doctype ("image/jpeg",size); char buf[64*1024]; int n; while ((n=fread(buf,1,sizeof(buf),fin))>0){ htmlwrite(buf,n); } fclose (fin); ret = 0; } return ret; } int util_sendfile (CONNECT_INFO &con, PARAM_STRING session, PARAM_STRING filename) { glocal int ret = -1; glocal CONNECT_INFO *con = &con; glocal const char *session = session.ptr; glocal bool is_mini_photo = strstr(filename.ptr,"/public/mini-photo.jpg")!=nullptr; glocal bool is_photo = strstr(filename.ptr,"/public/photo.jpg")!=nullptr; (con,session,filename,"",false); if (success){ glocal.ret = 0; util_sendfile_common(*glocal.con,info,content,more,handle,glocal.session); }else if (glocal.is_mini_photo){ glocal.ret = util_sendfile("/var/www/html/no-mini-photo.jpg"); }else if (glocal.is_photo){ glocal.ret = util_sendfile("/var/www/html/no-photo.jpg"); }else{ } return glocal.ret; } /* Send a file using the public api. The file is /username/file. We accept also username/file. So we extract the username */ int util_sendpublicfile (CONNECT_INFO &con, PARAM_STRING filename) { glocal int ret = -1; glocal CONNECT_INFO *con = &con; const char *pt = filename.ptr; if (*pt == '/') pt++; const char *start = pt; pt = strchr(pt,'/'); if (pt != NULL){ glocal const char *filename = pt; glocal string username = string(start,pt-start); (con,glocal.username,pt,0); if (!success){ if (strcmp(glocal.filename,"/project/photo.jpg")==0){ glocal.ret = util_sendfile ("/var/www/html/no-photo.jpg"); }else if (strcmp(glocal.filename,"/project/mini-photo.jpg")==0){ glocal.ret = util_sendfile ("/var/www/html/no-mini-photo.jpg"); } if (glocal.ret != 0) tlmp_warning ("Can't read public file %s for user %s: %s\n",glocal.filename,glocal.username.c_str(),msg); }else{ glocal.ret = 0; util_sendfile_common(*glocal.con,info,content,more,handle,"public"); } } return glocal.ret; } string util_flipspaces(PARAM_STRING src) { string ret = src.ptr; for (auto &c:ret){ if (c == ' ') c = '_'; } return ret; } static bool util_is_url(const char *txt, const char *&end,string &url) { bool ret = false; const char *pt; if (is_start_any_ofnc(txt,pt,"http://","https://")){ pt = txt; while (*pt > ' ' && is_not_in(*pt,'"','>')) pt++; url = string(txt,pt-txt); end = pt; ret = true; } return ret; } /* Format and print a ... with openitab() */ void util_print_span(PARAM_STRING url) { htmlprintf ("%s\n",url.ptr,url.ptr); } /* Format a ... with openitab() */ static string util_span(PARAM_STRING url) { return string("" + url.ptr + ""; } /* Format an open ... with openitab() (no closing */ static string util_open_span(PARAM_STRING url) { return string(""; } void util_clickable_img (PARAM_STRING url, const char *image_width, unsigned border) { htmlout (""); htmlprintf ("",image_width,border,url.ptr); htmlout (""); } /* Create the HTML for a clickable image (using javascript openintab()) */ string util_clickable_img (PARAM_STRING url, unsigned image_width) { string ret; ret.reserve(500); ret = util_open_span(url); ret += string_f(""; return ret; } /* Format a short message, remove the signature Escapes < and > Supports ? for URL */ string util_format_shortmsg (PARAM_STRING msg, unsigned nblines, size_t size, unsigned image_width) { const char *txt = msg.ptr; string ret; ret.reserve(nblines > 0 ? nblines*100 : 1000); unsigned pos=0; unsigned noline=0; if (nblines == 0) nblines=(unsigned)-1; while (*txt != '\0' && noline < nblines){ if (*txt == '\n'){ ret += "
\n"; pos=0; noline++; }else{ const char *pt; string url; if (util_is_url(txt,pt,url)){ ret += util_span (string(txt,pt-txt)); txt = pt-1; }else if (*txt == '<'){ if (is_start_any_ofnc(txt,pt,"
","","","","","","","","","","")){ while (txt < pt) ret += *txt++; txt--; // There is a txt++ at the end of the loop. }else{ ret += "<"; } }else if (*txt == '>'){ ret += ">"; }else if (*txt == '\t'){ unsigned nb = 4 - (pos%4); for (unsigned i=0; i\n" "\n" "Your browser does not support the video tag.\n" "\n" ,image_width,url.c_str()); ret += "
"; }else{ ret += "_VIDEO="; } txt--; }else if (is_start_any_of(txt,pt,"_IFRAME=")){ txt = pt; if (util_is_url(txt,pt,url)){ txt = pt; ret += util_open_span(url); ret += "
\n"; ret += string_f ("\n" ,url.c_str()); ret += "
"; }else{ ret += "_IFRAME="; } txt--; }else{ ret += *txt; pos++; } } txt++; } if (*txt != '\0' || (size != 0 && size != strlen(msg.ptr))){ if (ret.size() > 0 && ret[ret.size()-1] != '\n') ret += "
\n"; ret += "..."; } return ret; } string util_format_shortmsg (PARAM_STRING txt, unsigned image_width) { return util_format_shortmsg (txt,0,0,image_width); } // Send an HTML document. Does some remaping of relative URLs. Prevent scripting as well. void _F_public_page::sendhtml (const BOB_TYPE &content) { string tmp((const char*)content.getbuffer(),content.getsize()); const char *txt = tmp.c_str(); const char *tosend = txt; while (*txt != '\0'){ if (*txt == '<'){ // Check if this is