}
+sub validate_passwd {
+ my $p = shift;
+
+ my %result;
+ %result = ( 'fieldid' => $p->{'fieldid'} )
+ if $p->{'fieldid'} =~ /^\w+$/;
+
+ return { %result, 'password_invalid' => 'Enter new password' }
+ unless length($p->{'check_password'});
+
+ my $svc_acct;
+ if ($p->{'svcnum'}) {
+ # false laziness with myaccount_passwd
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { %result, 'error' => $session } if $context eq 'error';
+
+ $custnum =~ /^(\d+)$/ or die "illegal custnum";
+ my $search = " AND custnum = $1";
+ $search .= " AND agentnum = ". $session->{'agentnum'} if $context eq 'agent';
+
+ $svc_acct = qsearchs( {
+ 'table' => 'svc_acct',
+ 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum ) '.
+ 'LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ 'LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => { 'svcnum' => $p->{'svcnum'}, },
+ 'extra_sql' => $search, #important
+ } )
+ or return { %result, 'error' => "Service not found" };
+ # end false laziness
+ }
+
+ $svc_acct ||= new FS::svc_acct {};
+
+ my $error = $svc_acct->is_password_allowed($p->{'check_password'});
+ return { %result, 'password_invalid' => $error } if $error;
+ return { %result, 'password_valid' => 1 };
+}
+
sub list_tickets {
my $p = shift;
my($context, $session, $custnum) = _custoragent_session_custnum($p);
'reset_passwd' => 'MyAccount/reset_passwd',
'check_reset_passwd' => 'MyAccount/check_reset_passwd',
'process_reset_passwd' => 'MyAccount/process_reset_passwd',
+ 'validate_passwd' => 'MyAccount/validate_passwd',
'list_tickets' => 'MyAccount/list_tickets',
'create_ticket' => 'MyAccount/create_ticket',
'get_ticket' => 'MyAccount/get_ticket',
--- /dev/null
+<SCRIPT>
+function add_password_validation (fieldid) {
+ var inputfield = document.getElementById(fieldid);
+ inputfield.onchange = function () {
+ var fieldid = this.id+'_result';
+ var resultfield = document.getElementById(fieldid);
+ var svcnum = '';
+ var svcfield = document.getElementById(this.id+'_svcnum');
+ if (svcfield) {
+ svcnum = svcfield.options[svcfield.selectedIndex].value;
+ }
+ if (this.value) {
+ resultfield.innerHTML = '<SPAN STYLE="color: blue;">Validating password...</SPAN>';
+ send_xmlhttp('selfservice.cgi',
+ ['action','validate_password','fieldid',fieldid,'svcnum',svcnum,'check_password',this.value],
+ function (result) {
+ result = JSON.parse(result);
+ var resultfield = document.getElementById(result.fieldid);
+ if (resultfield) {
+ if (result.valid) {
+ resultfield.innerHTML = '<SPAN STYLE="color: green;">Password valid!</SPAN>';
+ } else if (result.error) {
+ resultfield.innerHTML = '<SPAN STYLE="color: red;">'+result.error+'</SPAN>';
+ } else {
+ result.syserror = result.syserror || 'Server error';
+ resultfield.innerHTML = '<SPAN STYLE="color: red;">'+result.syserror+'</SPAN>';
+ }
+ }
+ }
+ );
+ } else {
+ resultfield.innerHTML = '';
+ }
+ };
+}
+</SCRIPT>
<TR>
<TH ALIGN="right">Change password for account: </TH>
<TD>
- <SELECT NAME="svcnum">
+ <SELECT ID="new_password_svcnum" NAME="svcnum">
<%= foreach my $svc ( @svcs ) {
$OUT .= '<OPTION VALUE="'. $svc->{'svcnum'}. '"'.
( $svc->{'svcnum'} eq $svcnum ? ' SELECTED' : '' ). '>'.
<TR>
<TH ALIGN="right">New password: </TH>
- <TD><INPUT TYPE="password" NAME="new_password" SIZE="18"></TD>
+ <TD>
+ <INPUT ID="new_password" TYPE="password" NAME="new_password" SIZE="18">
+ <DIV ID="new_password_result"></DIV>
+<%= include('send_xmlhttp') %>
+<%= include('add_password_validation') %>
+<SCRIPT>
+add_password_validation('new_password');
+</SCRIPT>
+ </TD>
</TR>
<TR>
mason_comp port_graph
start_thirdparty finish_thirdparty
reset_passwd check_reset_passwd process_reset_passwd
+ validate_passwd
billing_history
);
process_suspend_pkg
switch_cust
history
+ validate_password
));
my @nologin_actions = (qw(
warn "WARNING: unrecognized action '$1'\n";
}
}
-
unless ( $nologin_actions{$action} ) {
my %cookies = CGI::Cookie->fetch;
);
}
+sub validate_password {
+ validate_passwd(
+ 'session_id' => $session_id,
+ map { $_ => scalar($cgi->param($_)) }
+ qw( fieldid svcnum check_password )
+ )
+}
+
#--
sub do_template {
--- /dev/null
+<SCRIPT>
+function rs_init_object () {
+ var A;
+ try {
+ A=new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e) {
+ try {
+ A=new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (oc) {
+ A=null;
+ }
+ }
+ if(!A && typeof XMLHttpRequest != "undefined")
+ A = new XMLHttpRequest();
+ if (!A)
+ alert("Can't create XMLHttpRequest object");
+ return A;
+}
+
+function send_xmlhttp (url,args,callback) {
+ args = args || [];
+ callback = callback || function (data) { return data };
+ var content = '';
+ for (var i = 0; i < args.length; i = i + 2) {
+ content = content + "&" + args[i] + "=" + escape(args[i+1]);
+ }
+ content = content.replace( /[+]/g, '%2B'); // fix unescaped plus signs
+
+ var xmlhttp = rs_init_object();
+ xmlhttp.open("POST", url, true);
+
+ xmlhttp.onreadystatechange = function() {
+ if (xmlhttp.readyState != 4)
+ return;
+ if (xmlhttp.status == 200) {
+ var data = xmlhttp.responseText;
+ callback(data);
+ }
+ };
+
+ xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ xmlhttp.send(content);
+}
+</SCRIPT>
+
didselector
);
+sub add_password_validation {
+ my $fieldid = shift;
+ my $out = '';
+ if ((-e './send_xmlhttp.html') && (-e './add_password_validation.html')) {
+ my $template = new Text::Template( TYPE => 'FILE',
+ SOURCE => "./send_xmlhttp.html",
+ DELIMITERS => [ '<%=', '%>' ],
+ UNTAINT => 1,
+ )
+ or die $Text::Template::ERROR;
+ $out .= $template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi' );
+ $template = new Text::Template( TYPE => 'FILE',
+ SOURCE => "./add_password_validation.html",
+ DELIMITERS => [ '<%=', '%>' ],
+ UNTAINT => 1,
+ )
+ or die $Text::Template::ERROR;
+ $out .= $template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi' );
+ $out .= <<ENDOUT;
+<SCRIPT>
+add_password_validation('$fieldid');
+</SCRIPT>
+ENDOUT
+ }
+ return $out;
+}
+
+
<FORM name="signup_form" action="<%= $self_url %>" METHOD="POST" onsubmit="return fixup_form();"><BR><FONT SIZE="+1"><B>First package</B></FONT>
<INPUT TYPE="hidden" NAME="promo_code" VALUE="<%= $promo_code %>">
<INPUT TYPE="hidden" NAME="reg_code" VALUE="<%= $reg_code %>">
-<TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<DIV STYLE="background: <%= $box_bgcolor %>; width: 100%">
+<TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=0>
<TR>
<TD COLSPAN=2><SELECT NAME="pkgpart">
$OUT .= <<ENDOUT;
<TR>
<TD ALIGN="right">Password</TD>
- <TD><INPUT TYPE="password" NAME="_password" VALUE="$_password"></TD>
+ <TD>
+ <INPUT ID="new_password" TYPE="password" NAME="_password" VALUE="$_password">
+ <DIV ID="new_password_result"></DIV>
+ENDOUT
+
+ $OUT .= add_password_validation('new_password');
+
+ $OUT .= <<ENDOUT;
+ </TD>
</TR>
<TR>
<TD ALIGN="right">Re-enter Password</TD>
%>
</TABLE>
+</DIV>
<%=
if ( @optional_packages ) {
--- /dev/null
+<%= use JSON;
+ encode_json({
+ 'valid' => $password_valid ? 1 : 0,
+ 'error' => $password_invalid,
+ 'syserror' => $error,
+ 'fieldid' => $fieldid,
+ 'password_debug' => $password_debug,
+ }); %>
+
display: none;
}
</STYLE>
-<A ID="<%$pre%>link" HREF="#" onclick="<%$pre%>toggle(true)">(<% mt('change') %>)</A>
+<A ID="<%$pre%>link" HREF="javascript:void(0)" onclick="<%$pre%>toggle(true)">(<% mt('change') %>)</A>
<DIV ID="<%$pre%>form" CLASS="passwordbox">
<FORM METHOD="POST" ACTION="<%$fsurl%>misc/process/change-password.html">
<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svc_acct->svcnum |h%>">