wordpress plugin, RT#75279
authorIvan Kohler <ivan@freeside.biz>
Tue, 18 Apr 2017 01:20:08 +0000 (18:20 -0700)
committerIvan Kohler <ivan@freeside.biz>
Tue, 18 Apr 2017 01:20:08 +0000 (18:20 -0700)
fs_selfservice/wordpress/LGPL-3 [new file with mode: 0644]
fs_selfservice/wordpress/README.txt [new file with mode: 0644]
fs_selfservice/wordpress/elements/error.php [new file with mode: 0644]
fs_selfservice/wordpress/example_login.php [new file with mode: 0644]
fs_selfservice/wordpress/example_selfservice.php [new file with mode: 0644]
fs_selfservice/wordpress/freeside_selfservice.php
fs_selfservice/wordpress/process_login.php [new file with mode: 0644]

diff --git a/fs_selfservice/wordpress/LGPL-3 b/fs_selfservice/wordpress/LGPL-3
new file mode 100644 (file)
index 0000000..65c5ca8
--- /dev/null
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/fs_selfservice/wordpress/README.txt b/fs_selfservice/wordpress/README.txt
new file mode 100644 (file)
index 0000000..879a96e
--- /dev/null
@@ -0,0 +1,47 @@
+Freeside signup and self-service plugin for Wordpress
+
+
+Installation:
+
+Copy this directory to your Wordpress plugins directory
+(For example, /var/lib/wordpress/wp-content/plugins/freeside/)
+
+Make sure the PHP XMLRPC module is installed
+(for example, "apt-get install php-xmlrpc")
+
+
+Activation:
+
+In Wordpress, go to Plugins -> Installed Plugins, find the "Freeside signup and
+self-service" plugin, and click "Activate".
+
+
+Configuration:
+
+In Wordpress, go to Settings -> General and set "Freeside self-service URL"
+to the 
+
+
+Freeside configuration:
+
+Go to Configuration -> Settings and turn on "selfservice-xmlrpc".  Restart
+Freeside services to turn on the daemon ("etc/init.d/freeside restart", or
+"service freeside restart")
+
+
+Firewall/network configuration:
+
+Allow the Wordpress machine to connect to port 8080 on the Freeside machine.
+Ensure the connection is on a secure network, or appropriately secured with a
+VPN or tunnel.
+
+
+Usage:
+
+See the included example_login.php, process_login.php and
+example_selfservice.php files
+
+For full API documentation including all available functions, their arguments
+and return data, see
+http://www.freeside.biz/mediawiki/index.php/Freeside:3:Documentation:Developer/FS/SelfService
+
diff --git a/fs_selfservice/wordpress/elements/error.php b/fs_selfservice/wordpress/elements/error.php
new file mode 100644 (file)
index 0000000..27ec0a4
--- /dev/null
@@ -0,0 +1,5 @@
+<?php 
+  $error = stripslashes_deep($_REQUEST['freeside_error']);
+?>
+<FONT SIZE="+1" COLOR="#ff0000"><?php echo htmlspecialchars($error); ?><?php if ($error) { echo '<BR><BR>'; } ?></FONT>
+
diff --git a/fs_selfservice/wordpress/example_login.php b/fs_selfservice/wordpress/example_login.php
new file mode 100644 (file)
index 0000000..1e3e6fe
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+
+require( dirname( __FILE__ ) . '/wp-blog-header.php' );
+get_header();
+
+$freeside = new FreesideSelfService();
+
+$login_info = $freeside->login_info();
+
+extract($login_info);
+
+$error = $_GET['error'];
+if ( $error ) {
+  $username = $_GET['username'];
+  $email    = $_GET['email'];
+  $domain   = $_GET['domain'];
+}
+
+?>
+<?php include(dirname(__FILE__).'/elements/error.php'); ?>
+
+<FORM ACTION="process_login.php" METHOD=POST>
+<INPUT TYPE="hidden" NAME="session" VALUE="login">
+
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
+
+<?php if ( $single_domain ) { ?>
+
+  <TR>
+    <TH ALIGN="right">Username </TH>
+    <TD>
+      <INPUT TYPE="text" NAME="freeside_username" VALUE="<?php echo htmlspecialchars($username); ?>"><?php if ( $single_domain ) { echo '@'.$single_domain; } ?>
+    </TD>
+  </TR>
+
+  <INPUT TYPE="hidden" NAME="freeside_domain" VALUE="<?php echo $single_domain ?>">
+
+<?php } else { ?>
+
+  <TR>
+    <TH ALIGN="right">Email address </TH>
+    <TD>
+      <INPUT TYPE="text" NAME="freeside_email" VALUE="<?php echo htmlspecialchars($email); ?>">
+    </TD>
+  </TR>
+
+<?php } ?>
+
+<TR>
+  <TH ALIGN="right">Password </TH>
+  <TD>
+    <INPUT TYPE="password" NAME="freeside_password">
+  </TD>
+</TR>
+<TR>
+  <TD COLSPAN=2 ALIGN="center"><INPUT TYPE="submit" VALUE="Login"></TD>
+</TR>
+</TABLE>
+</FORM>
+
+<?php if ( $phone_login ) { ?>
+
+  <B>OR</B><BR><BR>
+    
+  <FORM ACTION="process_login.php" METHOD=POST>
+  <INPUT TYPE="hidden" NAME="session" VALUE="login">
+  <TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
+  <TR>
+    <TH ALIGN="right">Phone number </TH>
+    <TD>
+      <INPUT TYPE="text" NAME="username" VALUE="<?php echo htmlspecialchars($username) ?>">
+    </TD>
+  </TR>
+  <INPUT TYPE="hidden" NAME="domain" VALUE="svc_phone">
+  <TR>
+    <TH ALIGN="right">PIN </TH>
+    <TD>
+      <INPUT TYPE="password" NAME="password">
+    </TD>
+  </TR>
+  <TR>
+    <TD COLSPAN=2 ALIGN="center"><INPUT TYPE="submit" VALUE="Login"></TD>
+  </TR>
+  </TABLE>
+  </FORM>
+
+<?php } ?>
+<?php get_footer(); ?>
+
diff --git a/fs_selfservice/wordpress/example_selfservice.php b/fs_selfservice/wordpress/example_selfservice.php
new file mode 100644 (file)
index 0000000..92da5bd
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+require( dirname( __FILE__ ) . '/wp-blog-header.php' );
+
+$freeside = new FreesideSelfService();
+
+error_log( "COOKIE: ". $_COOKIE['freeside_session_id'] );
+error_log( "COOKIE: ". $GLOBALS['FREESIDE_SESSION_ID'] );
+
+$customer_info = $freeside->customer_info_short( array(
+  'session_id' => $_COOKIE['freeside_session_id'],
+) );
+
+
+if ( isset($customer_info['error']) && $customer_info['error'] ) {
+  $error = $customer_info['error'];
+  wp_redirect('example_login.php?freeside_error='. urlencode($error));
+  die();
+}
+
+extract($customer_info);
+
+get_header();
+
+error_log( "COOKIE: ". $_COOKIE['freeside_session_id'] );
+
+?>
+
+<P>Hello <?php echo htmlspecialchars($name); ?></P>
+
+<?php if ( $signupdate_pretty ) { ?>
+  <P>Thank you for being a customer since <?php echo $signupdate_pretty; ?></P>
+<?php } ?>
+
+<P>Your account number is: <B><?php echo $display_custnum ?></B></P>
+
+<P>Your current balance is: <B><?php echo $balance_pretty ?></B></P>
+
+<?php echo $announcement ?>
+
+<!--
+your open invoices if you have any & payment link if you have one.  more insistant if you're late?
+<BR><BR>
+
+your tickets.  some notification if there's new responses since your last login 
+<BR><BR>
+
+anything else?
+-->
+
+<?php get_footer(); ?>
index 2041eed..5fe7aa7 100644 (file)
 <?php
 /*
-Plugin Name: Freeside signup and self-service plugin
+Plugin Name: Freeside signup and self-service
 Plugin URI:  http://freeside.biz/freeside
 Description: Call the Freeside signup and self-service APIs from within Wordpress
-Version:     0.20170403
+Version:     0.20170417
 Author:      Freeside Internet Services, Inc.
 Author URI:  https://freeside.biz/freeside/
-License:     GPL3
 License URI: https://www.gnu.org/licenses/gpl-3.0.html
 Text Domain: freeside_selfserivce
 Domain Path: /languages
+License:     LGPL
+
+The Freeside signup and self-service plugin is free software: you can
+redistribute it and/or modify it under the terms of the GNU Lesser General
+Public License as published by the Free Software Foundation, either version
+3 of the License, or any later version.
+The Freeside signup and self-service plugin is distributed in the hope that
+it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this plugin. If not, see
+https://www.gnu.org/licenses/lgpl-3.0.en.html
 */
 
 add_action('admin_init', 'freeside_admin_init' );
 
-function freeside_admin_init {
-  register_setting( 'misc', 'freeside_selfservice_url', 'https://freeside.server:8080' );
+add_action('init', 'freeside_init');
+
+function freeside_admin_init() {
+  register_setting( 'general', 'freeside_server', 'freeside.example.com' );
+  add_settings_field( 'freeside_server', 'Freeside server', 'freeside_server_input', 'general' );
+}
+
+function freeside_server_input() {
+  $value = get_option('freeside_server');
+  //$value = ($value ? $value : 'freeside.example.com');
+  ?>
+    <INPUT TYPE="text" ID="freeside_server" NAME="freeside_server" VALUE="<?php echo htmlspecialchars($value); ?>">
+  <?php
 }
 
-function flatten($hash) {
+//TODO: remove freeside_server on uninstall
+
+function freeside_init() {
+  //error_log("FINALLY action run ". $FREESIDE_PROCESS_LOGIN);
+
+  //error_log($GLOBALS['$FREESIDE_PROCESS_LOGIN']);
+  if ( ! $GLOBALS['FREESIDE_PROCESS_LOGIN'] ) {
+error_log("DACOOKIE: ". $_COOKIE['freeside_session_id']);
+    $GLOBALS['FREESIDE_SESSION_ID'] = $_COOKIE['freeside_session_id'];
+    return;
+  } else {
+    $GLOBALS['FREESIDE_PROCESS_LOGIN'] = false;
+  }
+
+  $freeside = new FreesideSelfService();
+
+  $response = $freeside->login( array( 
+    'email'    => strtolower($_POST['freeside_email']),
+    'username' => strtolower($_POST['freeside_username']),
+    'domain'   => strtolower($_POST['freeside_domain']),
+    'password' => $_POST['freeside_password'],
+  ) );
+
+  #error_log("[login] received response from freeside: $response");
+
+  $error = $response['error'];
+  error_log($error);
+
+  if ( $error ) {
+
+    $url  = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
+    $url .= $_SERVER['SERVER_NAME'];
+    $url .= $_SERVER['REQUEST_URI'];
+
+    wp_redirect(dirname($url). '/example_login.php?username='. urlencode($_POST['freeside_username']).
+                             '&domain='.   urlencode($_POST['freeside_domain']).
+                             '&email='.    urlencode($_POST['freeside_email']).
+                             '&freeside_error='.    urlencode($error)
+          );
+    exit;
+
+  }
+
+  // sucessful login
+
+  $session_id = $response['session_id'];
+
+  error_log("[login] logged into freeside with session_id=$freeside_session_id, setting cookie");
+
+// now what?  for now, always redirect to the main page (or the select a
+// customer diversion).
+// eventually, other options?
+
+  setcookie('freeside_session_id', $session_id);
+
+  $GLOBALS['FREESIDE_LOGIN_RESPONSE'] = $response;
+
+}
+
+function freeside_flatten($hash) {
   if ( !is_array($hash) ) return $hash;
   $flat = array();
 
@@ -34,29 +118,24 @@ function flatten($hash) {
   return($flat);
 }
 
-class FreesideSelfService  {
-
-    //Change this to match the location of your selfservice xmlrpc.cgi or daemon
-    #var $URL = 'https://localhost/selfservice/xmlrpc.cgi';
-    # XXX freeide_selfservice_url config value
-    #var $URL = 'http://localhost/selfservice/xmlrpc.cgi';
-    var $URL = get_opgion('freeside_selfservice_url');
+class FreesideSelfService {
 
     function FreesideSelfService() {
       $this;
     }
 
     public function __call($name, $arguments) {
+    
+        $URL = 'http://'. get_option('freeside_server'). ':8080';
+        error_log("[FreesideSelfService] $name called, sending to ". $URL);
 
-        error_log("[FreesideSelfService] $name called, sending to ". $this->URL);
-
-        $request = xmlrpc_encode_request("FS.ClientAPI_XMLRPC.$name", flatten($arguments[0]));
+        $request = xmlrpc_encode_request("FS.ClientAPI_XMLRPC.$name", freeside_flatten($arguments[0]));
         $context = stream_context_create( array( 'http' => array(
             'method' => "POST",
             'header' => "Content-Type: text/xml",
             'content' => $request
         )));
-        $file = file_get_contents($this->URL, false, $context);
+        $file = file_get_contents($URL, false, $context);
         $response = xmlrpc_decode($file);
         if (xmlrpc_is_fault($response)) {
             trigger_error("[FreesideSelfService] XML-RPC communication error: $response[faultString] ($response[faultCode])");
diff --git a/fs_selfservice/wordpress/process_login.php b/fs_selfservice/wordpress/process_login.php
new file mode 100644 (file)
index 0000000..2ddf27c
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+
+$GLOBALS['FREESIDE_PROCESS_LOGIN'] = true;
+//error_log($GLOBALS['$FREESIDE_PROCESS_LOGIN']);
+
+require( dirname( __FILE__ ) . '/wp-blog-header.php' );
+
+//add_action('muplugins_loaded', 'freeside_process_login');
+//error_log("action added");
+
+function notfreeside_process_login() {
+error_log("FINALLY action run");
+
+$freeside = new FreesideSelfService();
+
+$response = $freeside->login( array( 
+  'email'    => strtolower($_POST['email']),
+  'username' => strtolower($_POST['username']),
+  'domain'   => strtolower($_POST['domain']),
+  'password' => $_POST['password'],
+) );
+
+#error_log("[login] received response from freeside: $response");
+
+$error = $response['error'];
+
+if ( $error ) {
+
+  wp_redirect('example_login.php?username='. urlencode($username).
+                           '&domain='.   urlencode($domain).
+                           '&email='.    urlencode($email).
+                           '&freeside_error='.    urlencode($error)
+        );
+  exit;
+
+}
+
+// sucessful login
+
+$session_id = $response['session_id'];
+
+error_log("[login] logged into freeside with session_id=$session_id, setting cookie");
+
+// now what?  for now, always redirect to the main page (or the select a
+// customer diversion).
+// eventually, other options?
+
+setcookie('session_id', $session_id);
+
+}
+
+$response = $GLOBALS['FREESIDE_LOGIN_RESPONSE'];
+
+if ( $response['custnum'] || $response['svcnum'] ) {
+
+  error_log('redirecting to example_selfservice.php');
+  wp_redirect("example_selfservice.php");
+  exit;
+
+} elseif ( $response['customers'] ) {
+  error_log('sending header');
+  get_header();
+?>
+
+  <?php include('elements/error.php'); ?>
+
+  <FORM NAME="SelectCustomerForm" ACTION="process_select_cust.php" METHOD=POST>
+  <INPUT TYPE="hidden" NAME="action" VALUE="switch_cust">
+
+  <TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
+
+    <TR>
+      <TH ALIGN="right">Customer </TH>
+      <TD>
+        <SELECT NAME="custnum" ID="custnum" onChange="custnum_changed()">
+          <OPTION VALUE="">Select a customer
+          <?php foreach ( $response['customers'] AS $custnum => $customer ) { ?>
+            <OPTION VALUE="<?php echo $custnum ?>"><?php echo htmlspecialchars( $customer ) ?>
+          <?php } ?>
+        </SELECT>
+      </TD>
+    </TR>
+
+    <TR>
+      <TD COLSPAN=2 ALIGN="center"><INPUT TYPE="submit" ID="submit" VALUE="Select customer" DISABLED></TD>
+    </TR>
+
+  </TABLE>
+  </FORM>
+
+  <SCRIPT TYPE="text/javascript">
+
+  function custnum_changed () {
+    var form = document.SelectCustomerForm;
+    if ( form.custnum.selectedIndex > 0 ) {
+      form.submit.disabled = false;
+    } else {
+      form.submit.disabled = true;
+    }
+  }
+
+  </SCRIPT>
+
+<?php
+
+// } else {
+// 
+//   die 'login successful, but unrecognized info (no custnum, svcnum or customers)';
+  
+}
+
+?>
+
+<?php get_footer(); ?>
+