Refactor String Evaluations in dhtmlxGantt

I’ve been trying out dhtmlxGantt, and it seems great. However, my site runs a fairly strict content-security-policy that prevents the use of “unsafe” string evaluation functions such as eval() and new Function(“string”). It would be wonderful if you could refactor to remove those functions.

To get it to work, I made this patch for gantt.date.date_to_str() and gantt.date.str_to_date(), but I noticed there are other instances of eval(), and I haven’t looked closely enough to see if those will be a problem for me too.

gantt.date.date_to_str = function(format,utc){ return function(date){ var xdate, month, fullYear, day, hours, minutes, seconds; if (utc) { xdate=date.getUTCDate(); month=date.getUTCMonth(); fullYear=date.getUTCFullYear(); day=date.getUTCDay(); hours=date.getUTCHours(); minutes=date.getUTCMinutes(); seconds=date.getUTCSeconds(); isoWeek=gantt.date.getUTCISOWeek(date); } else { xdate=date.getDate(); month=date.getMonth(); fullYear=date.getFullYear(); day=date.getDay(); hours=date.getHours(); minutes=date.getMinutes(); seconds=date.getSeconds(); isoWeek=gantt.date.getISOWeek(date); } var replaced=format.replace(/%[a-zA-Z]/g,function(a){ switch(a){ case "%d": return gantt.date.to_fixed(xdate); case "%m": return gantt.date.to_fixed((month+1)); case "%j": return xdate; case "%n": return (month+1); case "%y": return gantt.date.to_fixed(fullYear%100); case "%Y": return fullYear; case "%D": return gantt.locale.date.day_short[day]; case "%l": return gantt.locale.date.day_full[day]; case "%M": return gantt.locale.date.month_short[month]; case "%F": return gantt.locale.date.month_full[month]; case "%h": return gantt.date.to_fixed((hours+11)%12+1); case "%g": return ((hours+11)%12+1); case "%G": return hours; case "%H": return gantt.date.to_fixed(hours); case "%i": return gantt.date.to_fixed(minutes); case "%a": return (hours>11?"pm":"am"); case "%A": return (hours>11?"PM":"AM"); case "%s": return gantt.date.to_fixed(seconds); case "%W": return gantt.date.to_fixed(isoWeek); default: return a; } }); return replaced; }; }; gantt.date.str_to_date = function(format,utc){ return function(date){ var set=[0,0,1,0,0,0], temp=date.match(/[a-zA-Z]+|[0-9]+/g), mask=format.match(/%[a-zA-Z]/g); for (var i=0; i<mask.length; i++){ switch(mask[i]){ case "%j": case "%d": set[2]=temp[i]||1; break; case "%n": case "%m": set[1]=(temp[i]||1)-1; break; case "%y": set[0]=temp[i]*1+(temp[i]>50?1900:2000); break; case "%g": case "%G": case "%h": case "%H": set[3]=temp[i]||0; break; case "%i": set[4]=temp[i]||0; break; case "%Y": set[0]=temp[i]||0; break; case "%a": case "%A": set[3]=set[3]%12+((temp[i]||'').toLowerCase()=='am'?0:12); break; case "%s": set[5]=temp[i]||0; break; case "%M": set[1]=gantt.locale.date.month_short_hash[temp[i]]||0; break; case "%F": set[1]=gantt.locale.date.month_full_hash[temp[i]]||0; break; default: break; } } if (utc) return new Date(Date.UTC(set[0],set[1],set[2],set[3],set[4],set[5])); else return new Date(set[0],set[1],set[2],set[3],set[4],set[5]); }; };

Thanks, hopefully you consider it!

“eval” used in two places, in both cases the related code can be just removed

  • attachEvent handling, necessary only for backward compatibility
  • json parsing, again used only when native JSON.parse is not available

The patch which you have provided is technically correct. It will result in a bit slower date parsing though.

I will add the above functionality to Gantt 2.2 feature list ( we can move eval based code to separate “compatibility” extension )

That will be great, look forward to it!