Dakusan’s Web Communication Framework
A communication framework between the client and server sides of a website with an emphasis on security.
Rating: 9 (This has been an ongoing library for a few years that has constantly shaped and evolved into exactly what I want and need (Along with DSQL)) Project Time: 2012-2014: 15 hours Languages: JavaScript, PHP Requirements: PHP Server; jQuery for the client module; The server optionally uses DSQL Downloads: Source (See any updates below for prior versions) Sections: Information, Content, Concepts, Notes, Updates, Comments
This helps facilitate quick, clean, and secure asynchronous communication for a website via AJAX and JSON.
The PHP and JS classes are independent and not required for each other. However, some of the functionality of each of the two classes complements the other.
2 parameters are received to the callback function:
Data:
The data returned by the server (which was encoded in JSON)
Result Member:
The return must be an object with a “Result” member
If using the DWCF PHP module, the Result member will automatically be “Success”, when using CallByAction(), if an object is returned without this member. This helps facilitate easier error handling
If UseTextProcessing, then the return from the server will be in JSON (not JSONP) and should be returned with a HTTP header Content-Type of “application/json”
If NOT UseTextProcessing, then the return from the server should be the JSON return data wrapped in the function provided by the “callback” request variable (in other words, JSONP) with a HTTP header Content-Type of “application/javascript”
However, this will only occur if the “callback” request variable is provided
error and complete:
Used internally
Request Names
The DWCF class keeps track of currently processing requests, via names provided to the DWCFRequest() function, to make sure two requests of the same name do not run at once
The name of a request is provided as the Name member in the Options parameter of the DWCFRequest() function
If the request’s name is null, this functionality will be ignored for that request
While the DWCF class greatly helps facilitate quick and easy communication via JSON, it is most importantly used for security by making sure all user input is properly sanitized and safe Request variables from $_REQUEST (or other such similar globals) should be retrieved through GetVars() and not directly read CallByAction() also helps to create physically separated action functions with guaranteed properly returned data
All functions and members are currently static
Functions
RetMsg($DataObj)
Outputs $DataObj encoded as JSON and optionally wrapped in a JSONP function (if the “callback” request variable is supplied), and then exits
“callback” must be an alphanumeric+underscore string of 1 to 100 characters (XSS precaution)
This is used to quickly output a return and exit without any more processing
Calls RetMsg() with an object that only contains the Result member set to $StrMessage
This is mainly used to quickly output errors
CallByAction()
Calls an action processing function determined by the “Action” request variable
The called function is named “Action_” followed by the “Action” request variable
After initial script preprocessing, this function should be the only function called to process different requested actions
This function will end the script after processing
If a string/scalar [non-object] is returned from the action function, it will be output via RetStr()
This makes returning error messages simple by just returning a string from the function
Otherwise, outputs via RetMsg() the returned (non-string) object from the called action function with the added member 'Result'=>'Success' (if Result is not already specified)
$_COOKIE is merged into $_REQUEST (duplicate $_REQUEST members take precedence) as cookies are not included by default on newer PHP versions
Pulls in, checks, and returns variables (found as members in $GetFrom)
Each requested variable is given individual constraints, and if any fail, an error will be generated for that variable
If all variables succeed against their constraints, an object is returned with all the requested variables (variable name’s as the member keys)
If any errors occur, a GetVarsException is thrown (which contains an array with error information)
Parameters:
VarArray[Required]
This is an object with the variable’s names as the member’s keys, and the value as an object of constraints
The optional constraints are as follows:
IsOptional: If this option is not set or is not (boolean)TRUE,the checked variable must be set and not null. Otherwise, if the checked variable is not set, the returned variable is set to null
RegEx: A regular expression to match against
MaxLen: The max (unicode) string length
MaxByteLen: The max (byte) string length
RegExOverrideErrorMessage: The error message that is used on a non-matching regular expression
IntRange: The [inclusive] range a number can be in. Array(Min, Max). All given variables/constraints are run through the “floor” function for comparison
FloatRange: The [inclusive] decimal range a number can be in. Array(Min, Max)
SQLLookup:
A query to confirm if a value is valid. This requires the DSQL library and confirms programmatically: if(DSQL::Query('SELECT COUNT(*) FROM '.$SQLLookup, ADDITIONAL_PARAMS)->FetchRow(0)!=0)
If SQLLookup is an array, then the first item is appended to the select part of the query, and the rest of the items are passed to the Query() function as additional parameters
%THEVAR% is replaced in parameters with the current variable’s value (can be part of a string)
%THEVAR-$VARNAME% acts the same as %THEVAR%, but takes its value from a variable already processed by GetVars named $VARNAME
Example: “%THEVAR-FooBar%” Will return the variable named “FooBar” which was already processed in the current GetVars run
If the first item is NULL, it will be removed, and the return will include full rows ("*") of the query result set in the format: Array('Value'=>$RESULT, 'QueryResult'=>Array(...))
AutomaticValidValues: An array of STRING values that, if a match occurs, make the variable considered to be valid before any other checks are processed
DoNotCheckEncoding: If given, do not confirm that the string is valid against the current unicode encoding
VarArray can also contain a member named “AutoVars” whose members are directly returned as variables. Variables set here can later be overwritten if checked for constraints
If a variable in VarArray has a value of null, the variable is considered to have no constraints
If a variable’s value is a boolean, it is checked against the strings “true” or “false”
GetFrom[Optional]
An object with the requested variables to check (as members)
Contains an “Errors” member, which is an array of ErrorItems generated by failed constraint checks of the different requested variables in the GetVars() function
Error Items
Format:
Array(
VariableName: The failed variable name
Constraints: The passed constraints for the failed variable
ErrorString: The generated error string
ConstraintName: The name of the constraint that failed (ex. “IntRange”). This can also be “NotScalar”, “NotSet”, and “Encoding”
<?//If requested, run the actionif(isset($_REQUEST['Action'])){require_once('DWCF.php');DWCF::CallByAction();//Actions are executed by function name}functionAction_TestAction()//Action=“TestAction” from the client{//Extract requested variablesextract(DWCF::GetVarsRS(Array('Value'=>Array('RegEx'=>'/^\d+$/',//Must match a number'RegExOverrideErrorMessage'=>'"Value" must be a number',//Let the user know the proper format for the variable'IntRange'=>Array(20,25)//Must be between 20 and 25, or an error is automatically returned),'AppendText'=>null//No constraints (except that it is a properly encoded string))));//This shows an example of returning an error string (this could have also been taken care of by a regular expression in GetVars)if($AppendText=='42')return'I told you not to do that';returnArray(//Since an array [object] is returned, this is considered successful'BoxNum'=>'5',//The box number on the user’s side to output the data//The output to show the user//Only AppendText needs to be escaped, as Value is already confirmed as a valid number (and converted to a number, anyways)'RetText'=>'Value plus 100 is '.($Value+100).'; <b>'.htmlspecialchars($AppendText,ENT_QUOTES,'UTF-8').'</b>');}functionAction_AnotherAction(){}//Another action name (unused)//Show the client formheader('Content-Type: text/html; charset=utf-8');?>
HTML Tie-Together Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>DWCF Example</title><metahttp-equiv="Content-Type"content="text/html; charset=utf-8"><script type="text/javascript"src="https://code.jquery.com/jquery-2.1.1.min.js"></script><script type="text/javascript"src="DWCF.js"></script></head><body><script type="text/javascript">
Javascript Code:
functionExecuteRequest(){//Update form state (note, these are all ran before we know if the request is a duplicate or not, which is not always a good idea)$('span').text('');//Clear out the text of all result spans$('#SendButton').attr('disabled',true);//Disable the submit button$('#State').text('Sending to server');//Let the user know the request is processing//Send the requestvarRunQuery=newDWCFRequest({Action:'TestAction',//Action to run on the PHP fileValue:$('#SendValue').val(),//“Value” variable via the text box to pass the PHP fileAppendText:$('#SendAppendText').val()//Another example variable},function(Data,ErrorCode){//The function to run on completion//Update the form state$('#State').text('Complete');//Let the user know the query has finished$('#SendButton').attr('disabled',false);//Reenable submit button$('#ErrorCode').text(this.ErrorCodeName(ErrorCode));//Let the user know the success/error of the result//If there was an error...if(ErrorCode){if(ErrorCode==this.ErrorCodes.ResultNotSuccessful)//If a not-successful error, let the user know what the error is$('#ErrorCode').text(function(Dummy,Val){returnVal+': '+Data.Result});return;//All errors handled so exit prematurely (other [catastrophic] errors handled by HandleError)}//Output the returned data string to the user in the appropriate output element$('#UserBox'+Data.BoxNum).html(Data.RetText);//If using .html(), make sure all data is properly escaped first!},{Name:'TestQuery'});//The name of the query is “TestQuery”. 2 queries with this name cannot be run at once}//Hook the form to perform the ExecuteRequest on submission$(document).ready(function(){$('form').submit(function(e){e.preventDefault();//Stop form submissiontry{ExecuteRequest();}catch(e){}//Catch all errors to make sure this form completes successfully (so the form stops submission)});});
HTML Tie-Together Code:
</script><formaction="#"><!-- Pressing enter on text boxes also submits the form, which can demonstrate the “Request Name” functionality --><tableborder=1cellspacing=0cellpadding=2><tr><td>Value (20-25)</td><td><inputtype=textid=SendValuevalue=21></td></tr><tr><td>Append Text</td><td><inputtype=textid=SendAppendTextvalue="Do not set this to 42"></td></tr><tr><td>Message</td><td><spanid=UserBox5></span></td></tr><tr><td>Error Code</td><td><spanid=ErrorCode></span></td></tr><tr><td>State</td><td><spanid=State></span></td></tr></table><br><inputtype=submitvalue=Sendid=SendButton></form></body></html>
Added ability via DSQL->$StrictMode variable to update MySQL strict mode
Added DSQL->RawQuery() function which takes just a query, and does no modification on it. I found this required due to extremely slow times on building very large queries.
Added DSQL->EscapeString() function which escapes a string for use in a mysql query. It has an optional parameter that adds single quotes around the result.
Added DSQL::PrepareInsertList() function which takes an array of names, and turns it into the following string: ['a', 'b', 'c'] => “(`a`, `b`, `c`) VALUES (?, ?, ?)”
Additional string parameters that have %THEVAR% are replaced with the value being checked
If the first item is NULL, it will be removed, and the return will include full rows ("*") of the query result set
Updated functionality:
json_encode() In RetMsg() and CallByAction() now use JSON_UNESCAPED_UNICODE
GetVars.VarArray.IsOptional now only triggers if it is (boolean)true
Added additional description specification to GetVars.VarArray.SQLLookup which says it uses the additional parameters as values to fill in the SQL Query
I finally decided to get on the bandwagon and go ahead and start submitting my stuff to Github too. DSQL and DWCF are already onthere, and I may or may not start adding a few older ones too. Here is my Dakusan profile.
Added v1.0 of the DWCF (Dakusan’s Web Communication Framework) project.
It is a communication framework between the client and server sides of a website with an emphasis on security. It helps facilitate quick, clean, and secure asynchronous communication for a website via AJAX and JSON.
To add comments, please go to the forum page for this project (guest comments are allowed for the Projects, Posts, and Updates Forums). Comments are owned by the user who posted them. We accept no responsibility for the contents of these comments.