From ffa240dfdeee4e904f88d218e6ab38af43c61e27 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Jan 2018 22:50:33 -0500 Subject: [PATCH 01/21] Add Chart.js to Composer --- composer.json | 3 ++- composer.lock | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c39ec9458d..77322add05 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "fxp/composer-asset-plugin": "~1.3", "bower-asset/base64": "^1.0", "npm-asset/jquery": "^1.11.2", - "npm-asset/jquery-colorbox": "^1.6" + "npm-asset/jquery-colorbox": "^1.6", + "bower-asset/Chart-js": "^2.7" }, "repositories": [ { diff --git a/composer.lock b/composer.lock index 003bef5869..ce9741ae13 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,40 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "228247829bf46d313ca451f94b87c7ef", + "content-hash": "6cf3b635594e443a7268a3bd9100d62d", "packages": [ + { + "name": "bower-asset/Chart-js", + "version": "v2.7.1", + "source": { + "type": "git", + "url": "https://github.com/chartjs/Chart.js.git", + "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/0fead21939b92c15093c1b7d5ee2627fb5900fff", + "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "./dist/Chart.js", + "bower-asset-ignore": [ + ".github", + ".codeclimate.yml", + ".gitignore", + ".npmignore", + ".travis.yml", + "scripts" + ] + }, + "license": [ + "MIT" + ], + "description": "Simple HTML5 charts using the canvas element.", + "time": "2017-10-28T15:01:52+00:00" + }, { "name": "bower-asset/base64", "version": "1.0.1", From 383641f58f509334e7982cee7316939fd2559b3c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Jan 2018 22:50:48 -0500 Subject: [PATCH 02/21] Migrate federation page to latest version of Chart.js --- view/global.css | 7 +-- view/templates/admin/federation.tpl | 82 ++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/view/global.css b/view/global.css index f3ca22b75a..2cfd046ca2 100644 --- a/view/global.css +++ b/view/global.css @@ -399,14 +399,9 @@ a { color: #00a700; } .federation-graph { - width: 400px; - height: 400px; - float: right; - margin: 20px; + margin: 0 auto; } .federation-network-graph { - width: 240px; - height: 240px; float: left; margin: 20px; } diff --git a/view/templates/admin/federation.tpl b/view/templates/admin/federation.tpl index 6904be6b92..cbd3a40a1e 100644 --- a/view/templates/admin/federation.tpl +++ b/view/templates/admin/federation.tpl @@ -1,5 +1,5 @@ - - + +

{{$title}} - {{$page}}

{{$intro}}

@@ -17,13 +17,40 @@

@@ -36,15 +63,42 @@ var myDoughnutChart = new Chart(ctx).Doughnut(FedData, { animateRotate : false, {{/if}} {{/foreach}} -
- +
    {{foreach $c[1] as $v}} @@ -55,4 +109,4 @@ var myDoughnutChart = new Chart(ctx).Doughnut(FedData, { animateRotate : false,
+ \ No newline at end of file From 269b3ee2a4a013ca5c188451bfcbae524c37ad4c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Jan 2018 22:51:31 -0500 Subject: [PATCH 03/21] Delete library/Chart.js --- library/Chart.js-1.0.2/Chart.min.js | 11 ----------- library/Chart.js-1.0.2/LICENSE.md | 7 ------- library/Chart.js-1.0.2/README.md | 20 -------------------- 3 files changed, 38 deletions(-) delete mode 100644 library/Chart.js-1.0.2/Chart.min.js delete mode 100644 library/Chart.js-1.0.2/LICENSE.md delete mode 100644 library/Chart.js-1.0.2/README.md diff --git a/library/Chart.js-1.0.2/Chart.min.js b/library/Chart.js-1.0.2/Chart.min.js deleted file mode 100644 index 3a0a2c8734..0000000000 --- a/library/Chart.js-1.0.2/Chart.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * Version: 1.0.2 - * - * Copyright 2015 Nick Downie - * Released under the MIT license - * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md - */ -(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),S=s.radians=function(t){return t*(Math.PI/180)},x=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),S=Math.round(f/v);(S>a||a>2*S)&&!h;)if(S>a)v*=2,S=Math.round(f/v),S%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,S=Math.round(f/v)}else v/=2,S=Math.round(f/v);return h&&(S=o,v=f/S),{steps:S,stepValue:v,min:p,max:p+S*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),st?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),R=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},T=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=R(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:T(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),tthis.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(S(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(S(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+x(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+x(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*S(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;ip&&(p=t.x+s,n=i),t.x-sp&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'
    <% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<% for (var i=0; i
  • <%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file diff --git a/library/Chart.js-1.0.2/LICENSE.md b/library/Chart.js-1.0.2/LICENSE.md deleted file mode 100644 index e10bc0ff1f..0000000000 --- a/library/Chart.js-1.0.2/LICENSE.md +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2013-2015 Nick Downie - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/library/Chart.js-1.0.2/README.md b/library/Chart.js-1.0.2/README.md deleted file mode 100644 index 7c4fa8bf6d..0000000000 --- a/library/Chart.js-1.0.2/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Chart.js - -[![Build Status](https://travis-ci.org/nnnick/Chart.js.svg?branch=master)](https://travis-ci.org/nnnick/Chart.js) [![Code Climate](https://codeclimate.com/github/nnnick/Chart.js/badges/gpa.svg)](https://codeclimate.com/github/nnnick/Chart.js) - - -*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org) - -## Documentation - -You can find documentation at [chartjs.org/docs](http://www.chartjs.org/docs/). The markdown files that build the site are available under `/docs`. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard. - -## Bugs, issues and contributing - -Before submitting an issue or a pull request to the project, please take a moment to look over the [contributing guidelines](https://github.com/nnnick/Chart.js/blob/master/CONTRIBUTING.md) first. - -For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](http://stackoverflow.com/questions/tagged/chartjs). - -## License - -Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT). From b963e7cc38b18b6ec7966384e3f901d2f03c28c3 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Jan 2018 11:16:16 -0500 Subject: [PATCH 04/21] Revert tabs into space in federation.tpl --- view/templates/admin/federation.tpl | 120 ++++++++++++++-------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/view/templates/admin/federation.tpl b/view/templates/admin/federation.tpl index cbd3a40a1e..70e3e9b06c 100644 --- a/view/templates/admin/federation.tpl +++ b/view/templates/admin/federation.tpl @@ -4,52 +4,52 @@

    {{$title}} - {{$page}}

    {{$intro}}

    {{if not $autoactive}} -

    {{$hint}}

    +

    {{$hint}}

    {{/if}}

    {{$legendtext}}

      {{foreach $counts as $c}} - {{if $c[0]['total'] > 0}} -
    • {{$c[0]['platform']}} ({{$c[0]['total']}}/{{$c[0]['users']}})
    • - {{/if}} + {{if $c[0]['total'] > 0}} +
    • {{$c[0]['platform']}} ({{$c[0]['total']}}/{{$c[0]['users']}})
    • + {{/if}} {{/foreach}}

    @@ -57,52 +57,52 @@ var myDoughnutChart = new Chart(ctx, { {{foreach $counts as $c}} {{if $c[0]['total'] > 0}} - {{$c[0]['platform']}} - {{$c[0]['total']}} - {{$c[0]['network']}} + {{$c[0]['platform']}} + {{$c[0]['total']}} + {{$c[0]['network']}}
      {{foreach $c[1] as $v}} -
    • {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }}{{$v['version']}}{{else}}{{$v['version']}}{{/if}} ({{$v['total']}})
    • +
    • {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }}{{$v['version']}}{{else}}{{$v['version']}}{{/if}} ({{$v['total']}})
    • {{/foreach}}
    From 910fda238338434bfbfa4f9542e3f2566db7196a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Jan 2018 11:24:56 -0500 Subject: [PATCH 05/21] Fix formatting in federation.tpl --- view/templates/admin/federation.tpl | 110 +++++++++++++++------------- 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/view/templates/admin/federation.tpl b/view/templates/admin/federation.tpl index 70e3e9b06c..c92af180c2 100644 --- a/view/templates/admin/federation.tpl +++ b/view/templates/admin/federation.tpl @@ -6,23 +6,22 @@ {{if not $autoactive}}

    {{$hint}}

    {{/if}} -

    {{$legendtext}} +

    {{$legendtext}}

      - {{foreach $counts as $c}} - {{if $c[0]['total'] > 0}} + {{foreach $counts as $c}} + {{if $c[0]['total'] > 0}}
    • {{$c[0]['platform']}} ({{$c[0]['total']}}/{{$c[0]['users']}})
    • - {{/if}} - {{/foreach}} + {{/if}} + {{/foreach}}
    -

    -
      - {{foreach $c[1] as $v}} -
    • {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }}{{$v['version']}}{{else}}{{$v['version']}}{{/if}} ({{$v['total']}})
    • - {{/foreach}} -
    - + }], + labels: [ + {{foreach $c[1] as $v}} + '{{$v['version']}}', + {{/foreach}} + ] +}; +var ctx = document.getElementById("{{$c[2]}}Chart").getContext("2d"); +var my{{$c[2]}}DoughnutChart = new Chart(ctx, { + type: 'doughnut', + data: {{$c[2]}}data, + options: { + legend: {display: false}, + animation: {animateRotate: false}, + responsive: false + } +}); + +
      + {{foreach $c[1] as $v}} +
    • + {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }} + {{$v['version']}} + {{else}} + {{$v['version']}} + {{/if}} + ({{$v['total']}}) +
    • + {{/foreach}} +
    + {{/if}} {{/foreach}} - \ No newline at end of file + From 6857392067f99b905803a7ccdb12559adef384ed Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Jan 2018 20:13:50 -0500 Subject: [PATCH 06/21] [Composer] Upgrade defuse/php-encryption to version ^2.0 --- composer.json | 2 +- composer.lock | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 77322add05..e8933ffbb6 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "ezyang/htmlpurifier": "~4.7.0", "mobiledetect/mobiledetectlib": "2.8.*", "league/html-to-markdown": "~4.4.1", - "defuse/php-encryption": "1.*", + "defuse/php-encryption": "^2.0", "pear/Text_LanguageDetect": "1.*", "pear/Text_Highlighter": "dev-master", "paragonie/random_compat": "^2.0", diff --git a/composer.lock b/composer.lock index ce9741ae13..46d8252bb8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "6cf3b635594e443a7268a3bd9100d62d", + "content-hash": "e2efb30af29afe0f5b9a001aac5da6d8", "packages": [ { "name": "bower-asset/Chart-js", @@ -71,28 +71,35 @@ }, { "name": "defuse/php-encryption", - "version": "v1.2.1", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/defuse/php-encryption.git", - "reference": "b87737b2eec06b13f025cabea847338fa203d1b4" + "reference": "5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/defuse/php-encryption/zipball/b87737b2eec06b13f025cabea847338fa203d1b4", - "reference": "b87737b2eec06b13f025cabea847338fa203d1b4", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689", + "reference": "5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689", "shasum": "" }, "require": { - "ext-mcrypt": "*", "ext-openssl": "*", + "paragonie/random_compat": "~2.0", "php": ">=5.4.0" }, + "require-dev": { + "nikic/php-parser": "^2.0|^3.0", + "phpunit/phpunit": "^4|^5" + }, + "bin": [ + "bin/generate-defuse-key" + ], "type": "library", "autoload": { - "files": [ - "Crypto.php" - ] + "psr-4": { + "Defuse\\Crypto\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -101,18 +108,29 @@ "authors": [ { "name": "Taylor Hornby", - "email": "havoc@defuse.ca" + "email": "taylor@defuse.ca", + "homepage": "https://defuse.ca/" + }, + { + "name": "Scott Arciszewski", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" } ], "description": "Secure PHP Encryption Library", "keywords": [ "aes", + "authenticated encryption", "cipher", + "crypto", + "cryptography", + "encrypt", "encryption", - "mcrypt", - "security" + "openssl", + "security", + "symmetric key cryptography" ], - "time": "2015-03-14T20:27:45+00:00" + "time": "2017-05-18T21:28:48+00:00" }, { "name": "ezyang/htmlpurifier", From 7af6cc8454cb7756f095453e36771f554c19244b Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Jan 2018 20:15:26 -0500 Subject: [PATCH 07/21] Add RINO version 3 encrypt/decrypt - Add legacy decrypt of RINO2 - Add fallback to RINO1 to encrypt --- mod/dfrn_notify.php | 34 +++++++++++++++++++++++++++------- src/Protocol/DFRN.php | 35 ++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index b81f26db9d..0d7e4bc7ef 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -6,6 +6,10 @@ * @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf */ +use Defuse\Crypto\Crypto; +use Defuse\Crypto\Exception\EnvironmentIsBrokenException; +use Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException; +use Defuse\Crypto\Key; use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; @@ -179,8 +183,8 @@ function dfrn_notify_post(App $a) { break; case 2: try { - $data = \Crypto::decrypt(hex2bin($data), $final_key); - } catch (\InvalidCiphertextException $ex) { // VERY IMPORTANT + $data = Crypto::legacyDecrypt(hex2bin($data), $final_key); + } catch (WrongKeyOrModifiedCiphertextException $ex) { // VERY IMPORTANT /* * Either: * 1. The ciphertext was modified by the attacker, @@ -190,12 +194,28 @@ function dfrn_notify_post(App $a) { */ logger('The ciphertext has been tampered with!'); xml_status(0, 'The ciphertext has been tampered with!'); - } catch (\CryptoTestFailedException $ex) { - logger('Cannot safely perform dencryption'); - xml_status(0, 'CryptoTestFailed'); - } catch (\CannotPerformOperationException $ex) { + } catch (EnvironmentIsBrokenException $ex) { logger('Cannot safely perform decryption'); - xml_status(0, 'Cannot safely perform decryption'); + xml_status(0, 'Environment is broken'); + } + break; + case 3: + $KeyObject = Key::loadFromAsciiSafeString($final_key); + try { + $data = Crypto::decrypt(hex2bin($data), $KeyObject); + } catch (WrongKeyOrModifiedCiphertextException $ex) { // VERY IMPORTANT + /* + * Either: + * 1. The ciphertext was modified by the attacker, + * 2. The key is wrong, or + * 3. $ciphertext is not a valid ciphertext or was corrupted. + * Assume the worst. + */ + logger('The ciphertext has been tampered with!'); + xml_status(0, 'The ciphertext has been tampered with!'); + } catch (EnvironmentIsBrokenException $ex) { + logger('Cannot safely perform decryption'); + xml_status(0, 'Environment is broken'); } break; default: diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index c05b5b3d63..bfe2fafaa8 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -8,6 +8,9 @@ */ namespace Friendica\Protocol; +use Defuse\Crypto\Crypto; +use Defuse\Crypto\Exception\EnvironmentIsBrokenException; +use Defuse\Crypto\Key; use Friendica\App; use Friendica\Content\OEmbed; use Friendica\Core\Config; @@ -22,11 +25,14 @@ use Friendica\Model\Term; use Friendica\Model\User; use Friendica\Object\Image; use Friendica\Protocol\OStatus; +use Friendica\Util\Crypto as FriendicaCrypto; use Friendica\Util\XML; use dba; use DOMDocument; use DOMXPath; +use HTMLPurifier; +use HTMLPurifier_Config; require_once 'boot.php'; require_once 'include/dba.php'; @@ -465,7 +471,7 @@ class DFRN /* get site pubkey. this could be a new installation with no site keys*/ $pubkey = Config::get('system', 'site_pubkey'); if (! $pubkey) { - $res = Crypto::newKeypair(1024); + $res = FriendicaCrypto::newKeypair(1024); Config::set('system', 'site_prvkey', $res['prvkey']); Config::set('system', 'site_pubkey', $res['pubkey']); } @@ -1291,30 +1297,29 @@ class DFRN switch ($rino_remote_version) { case 1: + case 2: + $rino = 1; + $rino_remote_version = 1; // Deprecated rino version! $key = openssl_random_pseudo_bytes(16); $data = self::aesEncrypt($postvars['data'], $key); break; - case 2: - // RINO 2 based on php-encryption + case 3: try { - $key = \Crypto::CreateNewRandomKey(); - } catch (\CryptoTestFailedException $ex) { + $KeyObject = Key::createNewRandomKey(); + } catch (EnvironmentIsBrokenException $ex) { logger('Cannot safely create a key'); return -4; - } catch (\CannotPerformOperationException $ex) { - logger('Cannot safely create a key'); - return -5; } + try { - $data = \Crypto::Encrypt($postvars['data'], $key); - } catch (\CryptoTestFailedException $ex) { + $data = Crypto::encrypt($postvars['data'], $key); + } catch (EnvironmentIsBrokenException $ex) { logger('Cannot safely perform encryption'); return -6; - } catch (\CannotPerformOperationException $ex) { - logger('Cannot safely perform encryption'); - return -7; } + + $key = $KeyObject->saveToAsciiSafeString(); break; default: logger("rino: invalid requested version '$rino_remote_version'"); @@ -2489,13 +2494,13 @@ class DFRN $item['body'] = OEmbed::HTML2BBCode($item['body']); - $config = \HTMLPurifier_Config::createDefault(); + $config = HTMLPurifier_Config::createDefault(); $config->set('Cache.DefinitionImpl', null); // we shouldn't need a whitelist, because the bbcode converter // will strip out any unsupported tags. - $purifier = new \HTMLPurifier($config); + $purifier = new HTMLPurifier($config); $item['body'] = $purifier->purify($item['body']); $item['body'] = @html2bbcode($item['body']); From de70007a463e45095e840cafa1130a7f69a7b048 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Jan 2018 20:15:56 -0500 Subject: [PATCH 08/21] Update RINO settings --- htconfig.php | 4 ++-- include/network.php | 2 +- mod/admin.php | 2 +- util/htconfig.vagrant.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/htconfig.php b/htconfig.php index 67db66e86f..86f2d14321 100644 --- a/htconfig.php +++ b/htconfig.php @@ -62,9 +62,9 @@ $a->config['php_path'] = 'php'; // Server-to-server private message encryption (RINO) is allowed by default. // Encryption will only be provided if this setting is set to a non zero value -// set to 0 to disable, 2 to enable, 1 is deprecated +// set to 0 to disable, 3 to enable -$a->config['system']['rino_encrypt'] = 2; +$a->config['system']['rino_encrypt'] = 3; // allowed themes (change this from admin panel after installation) diff --git a/include/network.php b/include/network.php index fe502bdb54..de7069a6d9 100644 --- a/include/network.php +++ b/include/network.php @@ -488,7 +488,7 @@ function validate_url($url) /// @TODO Really suppress function outcomes? Why not find them + debug them? $h = @parse_url($url); - if ((is_array($h)) && (dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { + if ((is_array($h)) && (@dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { return $url; } diff --git a/mod/admin.php b/mod/admin.php index eabbe36d3e..dfa6d627d2 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1336,7 +1336,7 @@ function admin_page_site(App $a) '$relocate_url' => ['relocate_url', t("New base url"), System::baseUrl(), t("Change base url for this server. Sends relocate message to all Friendica and Diaspora* contacts of all users.")], - '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), ["Disabled", "RINO1 (deprecated)", "RINO2"]], + '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), ["Disabled", "RINO3"]], '$worker_queues' => ['worker_queues', t("Maximum number of parallel workers"), Config::get('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")], '$worker_dont_fork' => ['worker_dont_fork', t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")], diff --git a/util/htconfig.vagrant.php b/util/htconfig.vagrant.php index cc4ade758a..5b50b9f399 100644 --- a/util/htconfig.vagrant.php +++ b/util/htconfig.vagrant.php @@ -52,7 +52,7 @@ $a->config['php_path'] = '/usr/bin/php'; // Encryption will only be provided if this setting is true and the // PHP mcrypt extension is installed on both systems -$a->config['system']['rino_encrypt'] = true; +$a->config['system']['rino_encrypt'] = 3; // default system theme From cadf8c5e5dc2636f51870d1a2be735028e95d28d Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Jan 2018 23:47:54 -0500 Subject: [PATCH 09/21] Bump new users RSA key strength --- src/Protocol/DFRN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index bfe2fafaa8..bf662cb1c8 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -471,7 +471,7 @@ class DFRN /* get site pubkey. this could be a new installation with no site keys*/ $pubkey = Config::get('system', 'site_pubkey'); if (! $pubkey) { - $res = FriendicaCrypto::newKeypair(1024); + $res = FriendicaCrypto::newKeypair(2048); Config::set('system', 'site_prvkey', $res['prvkey']); Config::set('system', 'site_pubkey', $res['pubkey']); } From 2e58120bbb27de1c27b76e27aef1ecfd17ee4a27 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 08:10:59 -0500 Subject: [PATCH 10/21] Fix RINO admin setting values --- mod/admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/admin.php b/mod/admin.php index dfa6d627d2..98cd8d0aca 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1336,7 +1336,7 @@ function admin_page_site(App $a) '$relocate_url' => ['relocate_url', t("New base url"), System::baseUrl(), t("Change base url for this server. Sends relocate message to all Friendica and Diaspora* contacts of all users.")], - '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), ["Disabled", "RINO3"]], + '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), [0 => "Disabled", 3 => "RINO3"]], '$worker_queues' => ['worker_queues', t("Maximum number of parallel workers"), Config::get('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")], '$worker_dont_fork' => ['worker_dont_fork', t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")], From 5db1717f4632a33da34e08b916816d7cba0e1878 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 08:13:32 -0500 Subject: [PATCH 11/21] Re-added missing RINO admin setting values --- mod/admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/admin.php b/mod/admin.php index 98cd8d0aca..ebb5509de0 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1336,7 +1336,7 @@ function admin_page_site(App $a) '$relocate_url' => ['relocate_url', t("New base url"), System::baseUrl(), t("Change base url for this server. Sends relocate message to all Friendica and Diaspora* contacts of all users.")], - '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), [0 => "Disabled", 3 => "RINO3"]], + '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), [0 => "Disabled", 1 => "RINO1 two-ways (deprecated)", 2 => "RINO1 sending/RINO2 receiving (deprectated)", 3 => "RINO3 (experimental)"]], '$worker_queues' => ['worker_queues', t("Maximum number of parallel workers"), Config::get('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")], '$worker_dont_fork' => ['worker_dont_fork', t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")], From 5bc7f4a4429afd95fd43966fb92c29b91cebe90e Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 11:25:48 -0500 Subject: [PATCH 12/21] Remove RINO2 and RINO3 --- htconfig.php | 5 ++--- mod/admin.php | 2 +- mod/dfrn_notify.php | 44 +------------------------------------ mod/install.php | 2 +- src/Protocol/DFRN.php | 21 ------------------ util/htconfig.vagrant.php | 5 ++--- view/templates/htconfig.tpl | 3 +-- 7 files changed, 8 insertions(+), 74 deletions(-) diff --git a/htconfig.php b/htconfig.php index 86f2d14321..1661dd30ed 100644 --- a/htconfig.php +++ b/htconfig.php @@ -61,10 +61,9 @@ $a->config['system']['maximagesize'] = 800000; $a->config['php_path'] = 'php'; // Server-to-server private message encryption (RINO) is allowed by default. -// Encryption will only be provided if this setting is set to a non zero value -// set to 0 to disable, 3 to enable +// set to 0 to disable, 1 to enable -$a->config['system']['rino_encrypt'] = 3; +$a->config['system']['rino_encrypt'] = 1; // allowed themes (change this from admin panel after installation) diff --git a/mod/admin.php b/mod/admin.php index ebb5509de0..9c286c11dd 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1336,7 +1336,7 @@ function admin_page_site(App $a) '$relocate_url' => ['relocate_url', t("New base url"), System::baseUrl(), t("Change base url for this server. Sends relocate message to all Friendica and Diaspora* contacts of all users.")], - '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), [0 => "Disabled", 1 => "RINO1 two-ways (deprecated)", 2 => "RINO1 sending/RINO2 receiving (deprectated)", 3 => "RINO3 (experimental)"]], + '$rino' => ['rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), [0 => "Disabled", 1 => "Enabled"]], '$worker_queues' => ['worker_queues', t("Maximum number of parallel workers"), Config::get('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")], '$worker_dont_fork' => ['worker_dont_fork', t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")], diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 0d7e4bc7ef..9c5aff2ead 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -6,10 +6,6 @@ * @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf */ -use Defuse\Crypto\Crypto; -use Defuse\Crypto\Exception\EnvironmentIsBrokenException; -use Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException; -use Defuse\Crypto\Key; use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; @@ -176,54 +172,16 @@ function dfrn_notify_post(App $a) { case 0: case 1: /* - *we got a key. old code send only the key, without RINO version. + * we got a key. old code send only the key, without RINO version. * we assume RINO 1 if key and no RINO version */ $data = DFRN::aesDecrypt(hex2bin($data), $final_key); break; - case 2: - try { - $data = Crypto::legacyDecrypt(hex2bin($data), $final_key); - } catch (WrongKeyOrModifiedCiphertextException $ex) { // VERY IMPORTANT - /* - * Either: - * 1. The ciphertext was modified by the attacker, - * 2. The key is wrong, or - * 3. $ciphertext is not a valid ciphertext or was corrupted. - * Assume the worst. - */ - logger('The ciphertext has been tampered with!'); - xml_status(0, 'The ciphertext has been tampered with!'); - } catch (EnvironmentIsBrokenException $ex) { - logger('Cannot safely perform decryption'); - xml_status(0, 'Environment is broken'); - } - break; - case 3: - $KeyObject = Key::loadFromAsciiSafeString($final_key); - try { - $data = Crypto::decrypt(hex2bin($data), $KeyObject); - } catch (WrongKeyOrModifiedCiphertextException $ex) { // VERY IMPORTANT - /* - * Either: - * 1. The ciphertext was modified by the attacker, - * 2. The key is wrong, or - * 3. $ciphertext is not a valid ciphertext or was corrupted. - * Assume the worst. - */ - logger('The ciphertext has been tampered with!'); - xml_status(0, 'The ciphertext has been tampered with!'); - } catch (EnvironmentIsBrokenException $ex) { - logger('Cannot safely perform decryption'); - xml_status(0, 'Environment is broken'); - } - break; default: logger("rino: invalid sent version '$rino_remote'"); xml_status(0, "Invalid sent version '$rino_remote'"); } - logger('rino: decrypted data: ' . $data, LOGGER_DATA); } diff --git a/mod/install.php b/mod/install.php index 2989f7fbea..b39e7c949a 100644 --- a/mod/install.php +++ b/mod/install.php @@ -63,7 +63,7 @@ function install_post(App $a) { $timezone = notags(trim($_POST['timezone'])); $language = notags(trim($_POST['language'])); $adminmail = notags(trim($_POST['adminmail'])); - $rino = 2; + $rino = 1; // connect to db dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true); diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index bf662cb1c8..76e8d58564 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -8,9 +8,6 @@ */ namespace Friendica\Protocol; -use Defuse\Crypto\Crypto; -use Defuse\Crypto\Exception\EnvironmentIsBrokenException; -use Defuse\Crypto\Key; use Friendica\App; use Friendica\Content\OEmbed; use Friendica\Core\Config; @@ -1304,23 +1301,6 @@ class DFRN $key = openssl_random_pseudo_bytes(16); $data = self::aesEncrypt($postvars['data'], $key); break; - case 3: - try { - $KeyObject = Key::createNewRandomKey(); - } catch (EnvironmentIsBrokenException $ex) { - logger('Cannot safely create a key'); - return -4; - } - - try { - $data = Crypto::encrypt($postvars['data'], $key); - } catch (EnvironmentIsBrokenException $ex) { - logger('Cannot safely perform encryption'); - return -6; - } - - $key = $KeyObject->saveToAsciiSafeString(); - break; default: logger("rino: invalid requested version '$rino_remote_version'"); return -8; @@ -1331,7 +1311,6 @@ class DFRN //logger('rino: sent key = ' . $key, LOGGER_DEBUG); - if ($dfrn_version >= 2.1) { if (($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) diff --git a/util/htconfig.vagrant.php b/util/htconfig.vagrant.php index 5b50b9f399..d5cb233575 100644 --- a/util/htconfig.vagrant.php +++ b/util/htconfig.vagrant.php @@ -49,10 +49,9 @@ $a->config['php_path'] = '/usr/bin/php'; // Server-to-server private message encryption (RINO) is allowed by default. -// Encryption will only be provided if this setting is true and the -// PHP mcrypt extension is installed on both systems +// set to 0 to disable, 1 to enable -$a->config['system']['rino_encrypt'] = 3; +$a->config['system']['rino_encrypt'] = 1; // default system theme diff --git a/view/templates/htconfig.tpl b/view/templates/htconfig.tpl index f9771c88da..1ecd9a2b4b 100644 --- a/view/templates/htconfig.tpl +++ b/view/templates/htconfig.tpl @@ -78,8 +78,7 @@ $a->config['max_import_size'] = 200000; $a->config['system']['maximagesize'] = 800000; // Server-to-server private message encryption (RINO) is allowed by default. -// Encryption will only be provided if this setting is set to a non zero value -// set to 0 to disable, 2 to enable, 1 is deprecated +// set to 0 to disable, 1 to enable $a->config['system']['rino_encrypt'] = {{$rino}}; From 633b133db630697dd2649b2ce3bab3ce54402c88 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 11:26:06 -0500 Subject: [PATCH 13/21] [Composer] Remove defuse/php-encryption dependency --- composer.json | 1 - composer.lock | 65 +-------------------------------------------------- 2 files changed, 1 insertion(+), 65 deletions(-) diff --git a/composer.json b/composer.json index e8933ffbb6..19fa2b1c38 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,6 @@ "ezyang/htmlpurifier": "~4.7.0", "mobiledetect/mobiledetectlib": "2.8.*", "league/html-to-markdown": "~4.4.1", - "defuse/php-encryption": "^2.0", "pear/Text_LanguageDetect": "1.*", "pear/Text_Highlighter": "dev-master", "paragonie/random_compat": "^2.0", diff --git a/composer.lock b/composer.lock index 46d8252bb8..a67eb0e1c7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "e2efb30af29afe0f5b9a001aac5da6d8", + "content-hash": "7fcbb730be98076fe8318b03c858f41c", "packages": [ { "name": "bower-asset/Chart-js", @@ -69,69 +69,6 @@ "description": "Base64 encoding and decoding", "time": "2017-03-25T21:16:21+00:00" }, - { - "name": "defuse/php-encryption", - "version": "v2.1.0", - "source": { - "type": "git", - "url": "https://github.com/defuse/php-encryption.git", - "reference": "5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/defuse/php-encryption/zipball/5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689", - "reference": "5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "paragonie/random_compat": "~2.0", - "php": ">=5.4.0" - }, - "require-dev": { - "nikic/php-parser": "^2.0|^3.0", - "phpunit/phpunit": "^4|^5" - }, - "bin": [ - "bin/generate-defuse-key" - ], - "type": "library", - "autoload": { - "psr-4": { - "Defuse\\Crypto\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Hornby", - "email": "taylor@defuse.ca", - "homepage": "https://defuse.ca/" - }, - { - "name": "Scott Arciszewski", - "email": "info@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "Secure PHP Encryption Library", - "keywords": [ - "aes", - "authenticated encryption", - "cipher", - "crypto", - "cryptography", - "encrypt", - "encryption", - "openssl", - "security", - "symmetric key cryptography" - ], - "time": "2017-05-18T21:28:48+00:00" - }, { "name": "ezyang/htmlpurifier", "version": "v4.7.0", From 035394cbf2c4edff8cd36595beaee2c1e9dcc4c4 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 11:34:56 -0500 Subject: [PATCH 14/21] RINO code cleanup - Restore original use Friendica\Util\Crypto - Remove RINO1 deprecation comments - Fix undefined variable $rino_remote_version --- mod/dfrn_notify.php | 10 +++------- src/Protocol/DFRN.php | 7 ++++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 9c5aff2ead..8903d66e35 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -143,7 +143,7 @@ function dfrn_notify_post(App $a) { // if local rino is lower than remote rino, abort: should not happen! // but only for $remote_rino > 1, because old code did't send rino version - if ($rino_remote_version > 1 && $rino < $rino_remote) { + if ($rino_remote > 1 && $rino < $rino_remote) { logger("rino version '$rino_remote' is lower than supported '$rino'"); xml_status(0, "rino version '$rino_remote' is lower than supported '$rino'"); } @@ -166,15 +166,11 @@ function dfrn_notify_post(App $a) { } } - #logger('rino: received key : ' . $final_key); - switch($rino_remote) { case 0: case 1: - /* - * we got a key. old code send only the key, without RINO version. - * we assume RINO 1 if key and no RINO version - */ + // we got a key. old code send only the key, without RINO version. + // we assume RINO 1 if key and no RINO version $data = DFRN::aesDecrypt(hex2bin($data), $final_key); break; default: diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 76e8d58564..305e3d3fde 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -22,7 +22,7 @@ use Friendica\Model\Term; use Friendica\Model\User; use Friendica\Object\Image; use Friendica\Protocol\OStatus; -use Friendica\Util\Crypto as FriendicaCrypto; +use Friendica\Util\Crypto; use Friendica\Util\XML; use dba; @@ -468,7 +468,7 @@ class DFRN /* get site pubkey. this could be a new installation with no site keys*/ $pubkey = Config::get('system', 'site_pubkey'); if (! $pubkey) { - $res = FriendicaCrypto::newKeypair(2048); + $res = Crypto::newKeypair(2048); Config::set('system', 'site_prvkey', $res['prvkey']); Config::set('system', 'site_pubkey', $res['pubkey']); } @@ -1295,9 +1295,10 @@ class DFRN switch ($rino_remote_version) { case 1: case 2: + // Force downgrade in case the remote server is still using the deprecated version 2 $rino = 1; $rino_remote_version = 1; - // Deprecated rino version! + $key = openssl_random_pseudo_bytes(16); $data = self::aesEncrypt($postvars['data'], $key); break; From dd07c47ab25d6fb29e3286d0d64900ed95d9df17 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 11:50:43 -0500 Subject: [PATCH 15/21] Code cleanup in Protocol\DFRN - Remove commented out code - Fix mixed quote style --- src/Protocol/DFRN.php | 48 +++++++++++-------------------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 305e3d3fde..507bdaa16b 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1310,8 +1310,6 @@ class DFRN $postvars['rino'] = $rino_remote_version; $postvars['data'] = bin2hex($data); - //logger('rino: sent key = ' . $key, LOGGER_DEBUG); - if ($dfrn_version >= 2.1) { if (($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) @@ -2162,8 +2160,6 @@ class DFRN * valid community action. Also forum_mode makes it valid for sure. * If neither, it's not. */ - - /// @TODO Maybe merge these if() blocks into one? if ($is_a_remote_action && $community && (!$r[0]["forum_mode"]) && (!$r[0]["wall"])) { $is_a_remote_action = false; logger("not a community action"); @@ -2365,21 +2361,12 @@ class DFRN $title = ""; foreach ($links as $link) { foreach ($link->attributes as $attributes) { - /// @TODO Rewrite these repeated (same) if () statements to a switch() - if ($attributes->name == "href") { - $href = $attributes->textContent; - } - if ($attributes->name == "rel") { - $rel = $attributes->textContent; - } - if ($attributes->name == "type") { - $type = $attributes->textContent; - } - if ($attributes->name == "length") { - $length = $attributes->textContent; - } - if ($attributes->name == "title") { - $title = $attributes->textContent; + switch ($attributes->name) { + case "href" : $href = $attributes->textContent; break; + case "rel" : $rel = $attributes->textContent; break; + case "type" : $type = $attributes->textContent; break; + case "length": $length = $attributes->textContent; break; + case "title" : $title = $attributes->textContent; break; } } if (($rel != "") && ($href != "")) { @@ -2630,16 +2617,6 @@ class DFRN if (($item["network"] != $author["network"]) && ($author["network"] != "")) { $item["network"] = $author["network"]; } - - /// @TODO maybe remove this old-lost code then? - // This code was taken from the old DFRN code - // When activated, forums don't work. - // And: Why should we disallow commenting by followers? - // the behaviour is now similar to the Diaspora part. - //if ($importer["rel"] == CONTACT_IS_FOLLOWER) { - // logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG); - // return; - //} } if ($entrytype == DFRN_REPLY_RC) { @@ -2656,13 +2633,12 @@ class DFRN $ev = bbtoevent($item["body"]); if ((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) { logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG); - /// @TODO Mixure of "/' ahead ... - $ev["cid"] = $importer["id"]; - $ev["uid"] = $importer["uid"]; - $ev["uri"] = $item["uri"]; - $ev["edited"] = $item["edited"]; - $ev['private'] = $item['private']; - $ev["guid"] = $item["guid"]; + $ev["cid"] = $importer["id"]; + $ev["uid"] = $importer["uid"]; + $ev["uri"] = $item["uri"]; + $ev["edited"] = $item["edited"]; + $ev["private"] = $item["private"]; + $ev["guid"] = $item["guid"]; $r = q( "SELECT `id` FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", From 2c284f30c243a66cc2046b31167a56974b60c5fe Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 11:58:26 -0500 Subject: [PATCH 16/21] Revert bumping the site RSA key strength to 2048 --- src/Protocol/DFRN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 507bdaa16b..60b093159c 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -468,7 +468,7 @@ class DFRN /* get site pubkey. this could be a new installation with no site keys*/ $pubkey = Config::get('system', 'site_pubkey'); if (! $pubkey) { - $res = Crypto::newKeypair(2048); + $res = Crypto::newKeypair(1024); Config::set('system', 'site_prvkey', $res['prvkey']); Config::set('system', 'site_pubkey', $res['pubkey']); } From 98344a9d08c84c82c2d3244c613e4a287f4fde19 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 12:06:09 -0500 Subject: [PATCH 17/21] Remove reference to RINO version 2 --- src/Protocol/DFRN.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 60b093159c..0d92d598cf 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1294,11 +1294,6 @@ class DFRN switch ($rino_remote_version) { case 1: - case 2: - // Force downgrade in case the remote server is still using the deprecated version 2 - $rino = 1; - $rino_remote_version = 1; - $key = openssl_random_pseudo_bytes(16); $data = self::aesEncrypt($postvars['data'], $key); break; From 4ed86adfab3886199cfff2f48b9728f3d46b87ff Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 20:14:26 -0500 Subject: [PATCH 18/21] [frio] Add max-width: 100% for video tags --- view/theme/frio/css/style.css | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 894f1b2dd6..105ef28d40 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -73,7 +73,7 @@ aside hr, section hr { border-color: rgba(238, 238, 238, $contentbg_transp); } -iframe, img { +iframe, img, video { max-width: 100%; } blockquote { @@ -3005,7 +3005,7 @@ section .profile-match-wrapper { float: left; } -/** +/** * Login page */ #login-submit-wrapper { @@ -3028,7 +3028,7 @@ section .profile-match-wrapper { .mod-home.is-not-singleuser nav.navbar, .mod-login nav.navbar { background-color: transparent } .mod-home.is-not-singleuser #topbar-second, -.mod-login #topbar-second { +.mod-login #topbar-second { background-color: transparent; box-shadow: unset; border: 0 @@ -3041,12 +3041,12 @@ section .profile-match-wrapper { .mod-home.is-not-singleuser .login-form > #login-form label, .mod-login #content #login-form label { - color: #eee; + color: #eee; } - + .mod-home.is-not-singleuser .login-panel-content, -.mod-login .login-panel-content { +.mod-login .login-panel-content { background-color: rgba(255,255,255,.85); } @@ -3058,7 +3058,7 @@ section .profile-match-wrapper { } .mod-home.is-not-singleuser .login-form > #login-form, - .mod-login #content #login-form { + .mod-login #content #login-form { background-color: #fff; padding: 1em; position: relative; @@ -3067,7 +3067,7 @@ section .profile-match-wrapper { .mod-home.is-not-singleuser .login-form > #login-form label, .mod-login #content #login-form label { - color: #444; + color: #444; } .mod-home.is-not-singleuser .login-form > #login-form::before, From 491a1373e07ac356eac8f0c40f7841416ef5c2a4 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 21:39:57 -0500 Subject: [PATCH 19/21] Fix autolink regular expression to include accents --- include/bbcode.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/bbcode.php b/include/bbcode.php index a6ffc39c18..ffc2387c3b 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -968,11 +968,12 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $simplehtml = fa // if the HTML is used to generate plain text, then don't do this search, but replace all URL of that kind to text if (!$forplaintext) { - // Autolink feature + // Autolink feature (thanks to http://code.seebz.net/p/autolink-php/) + $autolink_regex = "`([^\]\=\"']|^)(https?\://[^\s<]+[^\s<\.\)])`ism"; if ($simplehtml != 7) { - $Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@]+)/ism", '$1$2', $Text); + $Text = preg_replace($autolink_regex, '$1$2', $Text); } else { - $Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@]+)/ism", '$1[url]$2[/url]', $Text); + $Text = preg_replace($autolink_regex, '$1[url]$2[/url]', $Text); $Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'bb_style_url', $Text); $Text = preg_replace_callback("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", 'bb_style_url', $Text); From fee80a57bc9fb2294cbcdb448cedeceb99dc9480 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 21:51:42 -0500 Subject: [PATCH 20/21] Change /siteinfo to /servers for directory URL on follow page --- mod/dfrn_request.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index a5f18e07a3..4fd31e485e 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -638,8 +638,8 @@ function dfrn_request_content(App $a) $page_desc = t("Please enter your 'Identity Address' from one of the following supported communications networks:"); $invite_desc = sprintf( - t('If you are not yet a member of the free social web, follow this link to find a public Friendica site and join us today.'), - get_server() + t('If you are not yet a member of the free social web, follow this link to find a public Friendica site and join us today.'), + get_server() . '/servers' ); $o = replace_macros($tpl, [ From 4cca8280b4c9e765d754226d19af9a7bd49c6c71 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Jan 2018 00:32:37 -0500 Subject: [PATCH 21/21] Fix undefined variables PHP Notice - $order_string in include/dba - $limit_string in include/dba - $search in mod/search - $lang_list in include/pgettext.php --- include/dba.php | 2 ++ include/pgettext.php | 5 ++--- mod/search.php | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/dba.php b/include/dba.php index b1b689fdf7..d40090cf4d 100644 --- a/include/dba.php +++ b/include/dba.php @@ -1145,6 +1145,7 @@ class dba { $condition_string = self::buildCondition($condition); + $order_string = ''; if (isset($params['order'])) { $order_string = " ORDER BY "; foreach ($params['order'] AS $fields => $order) { @@ -1157,6 +1158,7 @@ class dba { $order_string = substr($order_string, 0, -2); } + $limit_string = ''; if (isset($params['limit']) && is_int($params['limit'])) { $limit_string = " LIMIT " . $params['limit']; } diff --git a/include/pgettext.php b/include/pgettext.php index 6ffed3ba35..403d520cc6 100644 --- a/include/pgettext.php +++ b/include/pgettext.php @@ -19,12 +19,12 @@ require_once "include/dba.php"; */ function get_browser_language() { + $lang_list = []; if (x($_SERVER, 'HTTP_ACCEPT_LANGUAGE')) { // break up string into pieces (languages and q factors) preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse); - $lang_list = []; if (count($lang_parse[1])) { // go through the list of prefered languages and add a generic language // for sub-linguas (e.g. de-ch will add de) if not already in array @@ -41,8 +41,7 @@ function get_browser_language() { } // check if we have translations for the preferred languages and pick the 1st that has - for ($i = 0; $i < count($lang_list); $i++) { - $lang = $lang_list[$i]; + foreach ($lang_list as $lang) { if ($lang === 'en' || (file_exists("view/lang/$lang") && is_dir("view/lang/$lang"))) { $preferred = $lang; break; diff --git a/mod/search.php b/mod/search.php index 60995e98a3..af9dd99563 100644 --- a/mod/search.php +++ b/mod/search.php @@ -135,6 +135,7 @@ function search_content(App $a) { Nav::setSelected('search'); + $search = ''; if (x($a->data,'search')) $search = notags(trim($a->data['search'])); else