11
Will_H
Re: an ajax aproach in theme
  • 2007/3/3 23:42

  • Will_H

  • Friend of XOOPS

  • Posts: 1786

  • Since: 2004/10/10



12
farshid
Re: an ajax aproach in theme
  • 2007/3/4 14:38

  • farshid

  • Just popping in

  • Posts: 34

  • Since: 2004/11/9


hi all;

in the demo site changes are:
1- form submition: post and get, try a search for get method and post a news for post method ( you can login using: demo,demo)
2- some redirections, sorry I was unable to do this from whithin the theme, so I made some changes to some files!
3- now you can use inline debug mode and view the resualts in the page. I will set the debug mod so you can test it. the great thing is that we can put the comment: <!--{xo-logger-output}--> in the out put and the debug data will be replaced by this comment.
4- getting left blocks on each request. so whene you go to the news module the block will show you extra menu items.


on theme.html top, now we have:
<{php}>
if(isset(
$_GET['ajaxpage']) || isset($_POST['ajaxpage'])){
    
header("Content-type: text/xml; charset=UTF-8");
    echo 
'<?xml version="1.0" encoding="utf-8"?>';
    if(isset(
$_GET['leftBlocks']) || isset($_POST['leftBlocks'])){
        echo 
'<ajax-response>';
        echo 
'<response type="object" id="blocks">';
        
$sid 1;
        
$title "title";
        
$content "Block Content!!";
        echo 
'<blocks sid="leftBlocks">';
        foreach(
$this->_tpl_vars['xoops_lblocks'] as $block){
            echo 
'<block bid="" title="'.$block['title'].'" module="">';
            echo 
'<content>';
            echo 
'<![CDATA['.$block['content'].']]>';
            echo 
'</content>';
            echo 
'</block>';
        }
        echo 
'</blocks>';
        echo 
'<dbug>';
        echo 
'<![CDATA[';
            <{/
php}>
            <!--{
xo-logger-output}-->
            <{
php}>
        echo 
']]>';
        echo 
'</dbug>';
        echo 
'</response>';
        echo 
'</ajax-response>';
    }else{
        
//echo '<!ATTLIST page content CDATA #IMPLIED>';
        
echo '<ajax-response>';
        echo 
'<response type="object" id="page">';
        global 
$xoopsOption$xoopsConfig$xoopsModule$xoopsRequestUri;
        
$url str_replace('?ajaxpage=1','?',($_SERVER['HTTP_HOST'].$xoopsRequestUri));
        
$url str_replace('&ajaxpage=1','',$url);
        
$url str_replace('?_=','?',$url);
        
$url str_replace('&_=','',$url);
        
$url str_replace('_=','',$url);
        
$url urlencode($url);
        if(
$xoopsModule){
            
$module $xoopsModule->getVar('dirname');
        }else{
            
$module '_nomodule_';
        }
        
//$title = "page title";
        
$title $this->_tpl_vars['xoops_sitename'] . ' - ' $this->_tpl_vars['xoops_pagetitle'];
        echo 
'<page url="'.$url.'" title="'.$title.'" module="'.$module.'" time="" href="">';
        echo 
'<content>';
        echo 
'<![CDATA['.$this->_tpl_vars['xoops_module_header'].$this->_tpl_vars['xoops_contents'].']]>';
        echo 
'</content>';
        echo 
'<dbug url="'.$url.'">';
        echo 
'<![CDATA[';
        <{/
php}>
        <!--{
xo-logger-output}-->
        <{
php}>
        echo 
']]>';
        echo 
'</dbug>';
        echo 
'</page>';
        
//echo '<page url="'.$url.'" title="'.$title.'" content="content" />';
        
echo '</response>';
        echo 
'</ajax-response>';
    }
}else{
<{/
php}>



the javascript to handle this is:
<script type="text/javascript" src="<{$xoops_imageurl}>Rico/prototype.js"></script>
<
script type="text/javascript" src="<{$xoops_imageurl}>Rico/rico.js"></script>
<
script language="javascript">

/*
 *
 * farshid:
 * function sanitizeATags
 * called when ever we need to make <a> tags call rico functions
 * 1- create and attach proper onClick attribute
 * 2- remove the href
 * 3- some criteria should exict as we need some links not vhanged (ex. <{$xoops_url}>/admin.php)
 *
 */
function sanitizeATags(){
    
/*
     * get all <a> tags and put them in atags variable
     */
    
atags document.getElementsByTagName('a');
    
/*
     * run throgh all atags, first we will check these:
     * atags[i].href != ''                                a element is linked to somewhere
     * atags[i].href.indexOf('admin') == -1                skip admin link(s)
     * atags[i].target != '_blank'                        skip links that will open in new window (ex. banners)
     * atags[i].href.indexOf('<{$xoops_url}>') == 0        href attribute starts with our site url
     *
     */
    
for(var 0atags.lengthi++){
        if((
atags[i].href != '') && (atags[i].href.indexOf('admin') == -1) && (atags[i].target != '_blank') && (atags[i].href.indexOf('<{$xoops_url}>') == 0)){
            
/*
             *
             * create an onClick attribute, set ints value to the proper function call: getPage(url)
             * the url comes from atag href attribute.
             * after creating it we will append it to the <a> element and set the href attribute: javascript:void(0);
             * this will disable the link from going anywhere.
             * 
             * NOTICE: setAttributeNode is not supported in explorer.
             *
             */
            
onClickAttribut document.createAttribute("onClick");
            
onClickAttribut.nodeValue "getPage('"+atags[i].href+"');";
            
atags[i].setAttributeNode(onClickAttribut);
            
//atags[i].setAttribute(onClickAttribut);
            
atags[i].href "javascript:void(0);";
        }
    }
}

/*
 *
 * farshid:
 * function sanitizeFormTags
 * called when ever we need to make <form> tags call rico functions
 *
 */
function sanitizeFormTags(){
    
/*
     * get all <form> tags and pit them in formtags variable
     */
    
formtags document.getElementsByTagName('form');
    
/*
     * run throgh all formtags:
     */
    
for(var 0formtags.lengthi++){
        
/*
         * first we will check if the form action is compelete, many forms
         * hase relative actions to the page they are loaded in.
         * this needs some work, to do its job properly.
         *
         * NOTICE: setAttributeNode is not supported in explorer.
         *
         */
         
if(formtags[i].getAttribute('action').indexOf('http://')!=0){
            
actionAttribut document.createAttribute("action");
            
actionAttribut.nodeValue '<{$xoops_url}>/'+formtags[i].getAttribute('action');
            
formtags[i].setAttributeNode(actionAttribut);
        }
        
        
/*
         *
         * Next we will check for these:
         * formtags[i].getAttribute('method') != ''                            form hase some methods!
         * formtags[i].getAttribute('method') == 'get'                        in this part we are going to sanitize forms with ger method
         * formtags[i].getAttribute('action').indexOf('<{$xoops_url}>'        action attrin starts with our site url
         * 
         */
        
if((formtags[i].getAttribute('method') != '') && (formtags[i].getAttribute('method') == 'get') && (formtags[i].getAttribute('action').indexOf('<{$xoops_url}>') == 0)){
            
/*
             * we are in our form with get methis, lets take all form elements
             */
            
formElements formtags[i].elements;
            
/*
             * loop throgh all elements to find submit and button types.
             */
            
for(var =0j<formElements.lengthj++){
                
/*
                 * in case we found a submit type, we will change the type to button (we do not want the form to be submited!)
                 * formElements[j].getAttribute('type') == 'submit'                            type is submit
                 * !formElements[j].getAttribute('onclick')                                    we will sanitize if there is no onClick attribute
                 * formElements[j].getAttribute('onclick').indexOf('submitFormGet')==0        and if it has some onClick it should be the one we have added.
                 *                                                                            so what! lets do it again, if we are on another page and the forms
                 *                                                                            array (document.forms) is changed then the button will submit another form.
                 */
                
if((formElements[j].getAttribute('type') == 'submit') && (!formElements[j].getAttribute('onclick') || (formElements[j].getAttribute('onclick').indexOf('submitFormGet')==0))){
                    
/*
                     * so we should change this submit type, and add the onClick attribute to it.
                     */
                    
typeAttribut document.createAttribute("type");
                    
typeAttribut.nodeValue "button";
                    
formElements[j].setAttributeNode(typeAttribut);
                    
/*
                     * this button will call submitFormGet(form)
                     * the form is the one we are in now: document.forms[i]
                     */    
                    
onClickAttribut document.createAttribute("onclick");
                    
onClickAttribut.nodeValue "submitFormGet(document.forms["+i+"]);";
                    
formElements[j].setAttributeNode(onClickAttribut);
                
/*
                 * so what if we find a button that we have alredy sanitized, but as we are in another page the refrence to form
                 * element is wrong! lets fix it now:
                 */
                
}else if((formElements[j].getAttribute('type') == 'button') && (!formElements[j].getAttribute('onclick') || (formElements[j].getAttribute('onclick').indexOf('submitFormGet')==0))){
                    
onClickAttribut document.createAttribute("onclick");
                    
onClickAttribut.nodeValue "submitFormGet(document.forms["+i+"]);";
                    
formElements[j].setAttributeNode(onClickAttribut);
                }
                
            }
        
/*
         * this part will do the same thing with the post method forms.
         * this part should be combined with the previous part.
         */
        
}else if((formtags[i].getAttribute('method') != '') && (formtags[i].getAttribute('method') == 'post') && (formtags[i].getAttribute('action').indexOf('<{$xoops_url}>') == 0)){
            
formElements formtags[i].elements;
            for(var 
=0j<formElements.lengthj++){
                if((
formElements[j].getAttribute('type') == 'submit')){
                    
typeAttribut document.createAttribute("type");
                    
typeAttribut.nodeValue "button";
                    
formElements[j].setAttributeNode(typeAttribut);
                    
                    if(!
formElements[j].getAttribute('onclick')){
                        
onClickAttribut document.createAttribute("onclick");
                        
/*
                         * some forms are posted based on the submitter name so lets pass the submiter name
                         * to the poster function.
                         */
                        
if(document.createAttribute("name")){
                            
onClickAttribut.nodeValue "submitFormPost(document.forms["+i+"],this.name);";
                        }else{
                            
onClickAttribut.nodeValue "submitFormPost(document.forms["+i+"],'');";
                        }
                        
formElements[j].setAttributeNode(onClickAttribut);
                    }else{
                        
alert(formElements[j].getAttribute('onclick'));
                        
/*
                        onClickAttribut = document.createAttribute("onclick");
                        onClickAttribut.nodeValue = "submitFormPost(document.forms["+i+"]);";
                        formElements[j].setAttributeNode(onClickAttribut);
                        */
                    
}
                }else if((
formElements[j].getAttribute('type') == 'button') && (formElements[j].getAttribute('onclick').indexOf('location=') == 0)){
                    
//alert(formElements[j].getAttribute('onclick'));
                        
onClickAttribut document.createAttribute("onclick");
                        
onClickAttribut.nodeValue "submitFormPostByLocation(document.forms["+i+"],this);";
                        
formElements[j].setAttributeNode(onClickAttribut);
                }
                
            }
        }
    }
}

/*
 *
 * function sanitizeModuleATags(string: module directory name)
 * just like sanitizeATags function, but for links in a module
 * called when ever we need to make <a> tags in a module
 * call rico functions
 * 1- create and attach proper onClick attribute
 * 2- remove the href
 * 3- some criteria should exict as we need some links not vhanged (ex. <{$xoops_url}>/admin.php)
 *
 * NOTIC: sanitizeATags function should always be called befor calling this function.
 *
 */
function sanitizeModuleATags(moduleDir){
    
/*
     * just get tags in the ajax_content part.
     */
    
modulearea document.getElementById('ajax_content');
    
atags modulearea.getElementsByTagName('a');
    for(var 
0atags.lengthi++){
        
/*
         * (atags[i].href != '')                                                we have some href to handle
         * atags[i].target != '_blank'                                            page is not opening in a new window
         * atags[i].getAttribute('target') != '_blank'                            I don't know why I put this here!
         * atags[i].href.indexOf('<{$xoops_url}>/modules/'+moduleDir) == 0        the link is in the module directory
         * atags[i].href.indexOf('userinfo.php') != -1                            the link is not pointing to user info, if it is so ot os alredy sanitized
         */
        
if((atags[i].href != '') && (atags[i].target != '_blank') && (atags[i].getAttribute('target') != '_blank') && ((atags[i].href.indexOf('<{$xoops_url}>/modules/'+moduleDir) == 0) || (atags[i].href.indexOf('userinfo.php') != -1))){
            
onClickAttribut document.createAttribute("onClick");
            
onClickAttribut.nodeValue "getPage('"+atags[i].href+"');";
            
atags[i].setAttributeNode(onClickAttribut);
            
//atags[i].setAttribute(onClickAttribut);
            
atags[i].href "javascript:void(0);";
        }else if((
atags[i].href.indexOf('<{$xoops_url}>') == 0) && (atags[i].getAttribute('target') != '_blank')){
            
onClickAttribut document.createAttribute("onClick");
            
xoopsUrl '<{$xoops_url}>';
            
onClickAttribut.nodeValue "getPage('<{$xoops_url}>/modules/"+moduleDir+atags[i].href.substring(xoopsUrl.length,atags[i].href.length)+"');";
            
atags[i].setAttributeNode(onClickAttribut);
            
//atags[i].setAttribute(onClickAttribut);
            
atags[i].href "javascript:void(0);";
        }
    }
}









/*
 * Create a page_object object which is responsible for handling our pages
 * This part has been modified from rico examples.
 */
var page_obj = Class.create();
/*
 * our page hase some attributes:
 * url:            page url
 * title:        page title that will be replaced to show current page title in the browser
 * module:        in the page is a module page: module directory name, else this will be: "_nomodule_"
 * time:        if the page is a redirecting page, the time to wait before redirecting
 * href:        the url we will redirect to after (time) seconds
 * content:        page content
 */
page_obj.attributes = [ "url""title""module""time""href""content" ];
page_obj.prototype = {
   
initialize: function(url) {
   },
   
ajaxUpdate: function(ajaxResponse) {
      
this.placePage(ajaxResponse.childNodes);
   },
   
placePage: function(page_responce) {
   
/*
    * page_responce is the xml part we have generated for the page;
    * it is somthing like this:
    *
    *    <page url="page url" title="page Title" module="module directory" time="" href="">
    *        <content>
    *            <![CDATA[not well formed html content here]]>
    *        </content>
    *        <dbug url="localhost%3A81%2Fxoops1016ajax%2F%3F">
    *            <![CDATA[not well formed html dbug data here]]>
    *        </dbug>
    *    </page>
    * 
    * page content and debug data will be loaded as CDATA section.
    * other data (attributes) are automaticaly mapped by Rico.
    */
         
var pageHolder '';
      
/*
       * get title, url and module directory.
       */
        
pageTitle page_responce[0].getAttribute('title');
        
pageUrl page_responce[0].getAttribute('url');
        
pageModule page_responce[0].getAttribute('module');
        
/*
         * get redirect time and url, and see if we should do redirect the page!
         */
        
redirectTime page_responce[0].getAttribute('time');
        
redirectUrl decodeURIComponent(page_responce[0].getAttribute('href'));
        
shouldRedirect = ((redirectTime != '') && (redirectUrl != ''));
        
/*
         * get page content and debug data
         */
        
pageHolder +=  page_responce[0].childNodes[0].childNodes[0].nodeValue;
        
debugData page_responce[0].childNodes[1].childNodes[0].nodeValue;
        
/*
         * set page title, content and debug data.
         */
        
document.title pageTitle;
        
document.getElementById('ajax_content').innerHTML pageHolder;
        
document.getElementById('debugWindowDebugArea').innerHTML 'Debug Data for URL: '+decodeURIComponent(pageUrl)+'n'+debugData;
        
document.getElementById('debugWindowDebugArea').style.visibility 'visible';
        
/*
         * if we are in a module sanitize module tags, else
         * do normal sanitize.
         */
        
if(pageModule != '_nomodule_'){
            
sanitizeModuleATags(pageModule);
        }else{
            
sanitizeATags();
        }
        
/*
         * sanitze forms
         */
        
sanitizeFormTags();
        
/*
         * inform user that the page is loaded and
         * give him/her a link to the main url.
         */
        
document.getElementById('pageLoadingMessage').innerHTML 'main page url: <a href="http://'+decodeURIComponent(pageUrl)+'" target="_blank">http://'+decodeURIComponent(pageUrl) + '</a>';
        
/*
         * if we should redirect, call the getPage(url) function after time*1000 milsec
         */
        
if(shouldRedirect){
            
window.setTimeout("getPage('"+redirectUrl+"')",redirectTime*1000);
        }
   }
}
var 
page_obj;


/*
 * this is the same as page object, just for blocks,
 * right now just left blocks.
 *
 */
var block_obj = Class.create();
block_obj.attributes = [ "bid""title""module""content" ];

block_obj.prototype = {
   
initialize: function(url,blockSide) {
   
this.url url;
   
this.blockSide blockSide;
   },
   
ajaxUpdate: function(ajaxResponse) {
      
this.placeBlock(ajaxResponse.childNodes);
   },
   
placeBlock: function(block_responce) {
         var 
blockHolder '';
      
blocks block_responce[0].childNodes;
      
elementToAdd document.getElementById('leftcolumn');
      
elementToAdd.innerHTML '';
      for(var 
i=0;i<blocks.length;i++){
        
addBlockToPage(this.blockSide,blocks[i].attributes['title'].nodeValue,blocks[i].childNodes[0].childNodes[0].nodeValue);
      }
      
sanitizeATags();
      
sanitizeFormTags();
      
document.getElementById('blockLoadingMessage').innerHTML '';
   }
}
var 
block_obj;







function 
addBlockToPage(blockSide,blockTitle,blockContent){
    switch(
blockSide){
        case 
'Left':
        
blockElement document.getElementById('leftcolumn');
        break;
    }
    
    
newBlockTitleDiv document.createElement('div');
    
classAttrib document.createAttribute("class");
    
classAttrib.nodeValue "blockTitle";
    
newBlockTitleDiv.setAttributeNode(classAttrib);
    
newBlockTitleDiv.innerHTML blockTitle;
    
blockElement.appendChild(newBlockTitleDiv);
    
    
newBlockContentDiv document.createElement('div');
    
classAttrib document.createAttribute("class");
    
classAttrib.nodeValue "blockContent";
    
newBlockContentDiv.setAttributeNode(classAttrib);
    
newBlockContentDiv.innerHTML blockContent;
    
blockElement.appendChild(newBlockContentDiv);
    
}







function 
registerAjaxPage(url) {
    
document.getElementById('pageLoadingMessage').innerHTML 'Loading Page, Use this link if the page failed Loading: <a href="'+url+'" target="_blank">'+url+'</a>';
    
ajaxEngine.registerRequest'getPage'url );
    
//ajaxEngine.registerAjaxElement( 'ajax_content' );
    
ajaxEngine.registerAjaxObject'page', new page_obj(url) );
}

function 
getPage(url) {
    
registerAjaxPage(url);
    
ajaxEngine.sendRequest'getPage'"ajaxpage=1" );
    
getLeftBlocks(url);
}

function 
registerAjaxBlocks(url,blockSide) {
    
document.getElementById('blockLoadingMessage').innerHTML ' and Loading '+blockSide+' Blocks...';
    if(
blockSide == 'Left'){
    
ajaxEngine.registerRequest'getLeftBlocks'url );
    }
    
ajaxEngine.registerAjaxObject'blocks', new block_obj(url,blockSide) );
}

function 
getLeftBlocks(url){
    
registerAjaxBlocks(url,'Left');
    
params_arr = Array("ajaxpage=1","leftBlocks=1");
    
params params_arr.join('&');
    
ajaxEngine.sendRequest'getLeftBlocks', {parameters:params} );
}

function 
submitFormGet(form){
    var 
formElements form.elements;
    var 
formParams = Array('ajaxpage=1');
    for(var 
=0j<formElements.lengthj++){
        switch(
formElements[j].type){
            
            case 
'text':
            case 
'hidden':
            
formParams.push(encodeURIComponent(formElements[j].getAttribute('name'))+"="+encodeURIComponent(formElements[j].value));
            break;
            
            case 
'checkbox':
            if(
formElements[j].checked){
                
formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
            }
            break;
            
            case 
'select-one':
            
formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
            break;
            
            
        }
//switch
        
    
}
    
registerAjaxPage(form.getAttribute('action'));
    var 
params formParams.join('&');
    
ajaxEngine.sendRequest'getPage', {parameters:params} );
}




function 
submitFormPost(form,elementName){
    var 
formElements form.elements;
    var 
formParams = Array('ajaxpage=1');
    if(
elementName != ''){
        
formParams.push(elementName+'='+elementName);
    }
    
elements '';
    for(var 
=0j<formElements.lengthj++){
        
elements += formElements[j].type+'n';
        if(
formElements[j].getAttribute('name') != null){
            switch(
formElements[j].type){
                
                case 
'text':
                case 
'hidden':
                case 
'select-one':
                case 
'textarea':
                case 
'password':
                
formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
                break;
                
                case 
'checkbox':
                case 
'radio':
                if(
formElements[j].checked){
                
formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
                }
                break;
                
                case 
'file':
                
formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
                break;
                
            }
//switch
        
}
        
    }
    
registerAjaxPage(form.getAttribute('action'));
    var 
params formParams.join('&');
    
ajaxEngine.sendRequest'getPage', {method:'post',parameters:params} );
}



function 
submitFormPostByLocation(form,element){

    
//var formElements = form.elements;
    //var Location = element.value;
    //var formParams = Array('ajaxpage=1');
    
alert('called');
    
//elements = '';
    /*
    for(var j =0; j<formElements.length; j++){
        //elements += formElements[j].type+'n';
        
        switch(formElements[j].type){
            
            case 'text':
            case 'hidden':
            formParams.push(encodeURIComponent(formElements[j].getAttribute('name'))+"="+encodeURIComponent(formElements[j].value));
            break;
            
            case 'checkbox':
            if(formElements[j].checked){
                formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
            }
            break;
            
            case 'select-one':
            formParams.push(formElements[j].getAttribute('name')+"="+encodeURIComponent(formElements[j].value));
            break;
            
            
        }//switch
        
        
    }
    */
    //formParams.push(encodeURIComponent(element.getAttribute('name'))+"="+encodeURIComponent(formElements[j].value));
    //alert(elements);
    //registerAjaxPage(form.getAttribute('action'));
    //var params = formParams.join('&');
    //alert(params);
    //ajaxEngine.sendRequest( 'getPage', {method:'post',parameters:params} );
}
</
script>


The code has some comments that I wish helps you.

I am going to do something new: bringing the admin area to XOOPS front side, just like liferay portal.
and another idea is a full flash theme based on this aproach, I am thinking of this, any ideas? or do you think this is good or bad?

there is some other changes in the theme, I will put the file for download as soon as possible.

and thanks for all your comments;

@highlander
I found the article in French, so I need the English version.

13
xguide
Re: an ajax aproach in theme
  • 2007/3/4 15:38

  • xguide

  • Just popping in

  • Posts: 43

  • Since: 2005/5/11


Hello farshid,

Nice effort but a kind of patchwork that may creates some more security holes in XOOPS 2.0.16

Before you push further your efforts to make this old code alike a web 2.0 application, you should check the last javascript security anouncements.

Before the security holes are patched. Examine the key factors of vulnerabilities

.Ajax calls are scattered all over the browser page and can be invoked by respective events.
.Input and outgoing content validation confusion
.It is also possible to load JavaScript in the browser that forces the browser to make cross-domain calls and opens up security holes. This can be lethal and leveraged by virus and worms.
.Browsers can invoke an Ajax call and perform data serialization. It can fetch JS array, Objects, Feeds, XML files, HTML blocks and JSON. If any of these serialization blocks can be intercepted and manipulated, the browser can be forced to execute malicious scripts.
.Ajax opens up a backend channel and fetches information from the server and passes it to the DOM; (update browser’s page memory by calling customized functions or the eval() function) an insecure call can range from a session compromise to the execution of malicious content.

You'll found out there a lot more issues.
If google, yahoo and many other services using web 2.0 apps are been victims of this new vulnerabilities. Can you imagine... a XOOPS site...

Waiting for a XOOPS patch.



14
farshid
Re: an ajax aproach in theme
  • 2007/3/4 16:14

  • farshid

  • Just popping in

  • Posts: 34

  • Since: 2004/11/9


Hello xguide;

as I said this is just an idea, so I do not understand the term:
Quote:
kind of patchwork


as you mentioned this will open some security holes in xoops, well I think any code that is born may have some problems, as we can see there are many modules, and lets say generaly -codes-, not just in XOOPS but in many open source (and...) software that have such a problem.
I don't think I have added any thing to xoops! so I don't now why you should be afraid of security problems!

And about javascript, OK, maybe you are right but I don't know if there is some problems with javascript or not! and if yes that would be for all kind of scripts, Ajax or none Ajaxed ones!
do you think javascript generally have problems or just the new Ajax? and what should we do? do not use it?

at last if you think I am doing something wrong explain it to me more, this way you are helping me and saving me from falling!

I have an online site for demo, and I will be glad if you can show me some problems, I will learn for sure, and for others it is good too.

15
xguide
Re: an ajax aproach in theme
  • 2007/3/4 17:59

  • xguide

  • Just popping in

  • Posts: 43

  • Since: 2005/5/11


Hello farshid,

Quote:
...as we can see there are many modules, and lets say generaly -codes-, not just in xoops...


You right. If we check XOOPS code we can see it's not completely object oriented. Part is old nuke, other part is Onokazu OO approach. Part is modules developers code style. Similar to any include of ajax library.

I've also check Wanikoo approach. As he says, XOOPS need a recode. To less vulnerabilities, just use the client dom-fx to improve interaction and user interface.

Until XOOPS 2.3 comes out and fixes the security holes.

Otherwise, great effort. We could apply this in a XOOPS intranet solution.

16
amiross
Re: an ajax aproach in theme
  • 2007/3/5 7:28

  • amiross

  • Just popping in

  • Posts: 7

  • Since: 2004/11/17


Xguide,

Are you indicating that generally there are vulnerabilites with AJAX or the way AJAX is implemented here?

Could you describe the vulnerabilities that you named a little bit more and what, if any, solutions to that?

17
xguide
Re: an ajax aproach in theme
  • 2007/3/5 14:24

  • xguide

  • Just popping in

  • Posts: 43

  • Since: 2005/5/11


Quote:

amiross wrote:
Xguide,

Are you indicating that generally there are vulnerabilites with AJAX or the way AJAX is implemented here?


Yes.

Quote:
Could you describe the vulnerabilities that you named a little bit more and what, if any, solutions to that?


To keep XOOPS sites safety. No.


Never use XOOPS 2.0.16 without Mr. Gijoe module protector.

Wait for Mr. Skalpa XOOPS 2.3 release.


(hope the roadmap will be update soon)

18
farshid
Re: an ajax aproach in theme
  • 2007/3/6 18:29

  • farshid

  • Just popping in

  • Posts: 34

  • Since: 2004/11/9


Hi all;

I am a little busy, so sorry for the delay, I have just uploaded new theme: http://www.fanafzar.com/uploads/defaultaj.rar
just if you need Rico files: http://www.fanafzar.com/uploads/Rico.rar

NOTE: DO NOT USE THIS CODE ON ANY SITE - JUST FOR TESTING PURPOSE

after setting the theme to be used in preferences, we need to modify 2 files:

1- include/functions.php
around line 400 find:
if (defined('SID') && (! isset($_COOKIE[session_name()]) || ($xoopsConfig['use_mysession'] && $xoopsConfig['session_name'] != '' && !isset($_COOKIE[$xoopsConfig['session_name']])))) {
        if (!
strstr($url'?')) {
            
$url .= '?' SID;
        } else {
            
$url .= '&amp;'.SID;
        }
    }


add this code just after the above:
if (!strstr($url'?')) {
            
$url .= '?ajaxpage=1';
        } else {
            
$url .= '&amp;ajaxpage=1';
        }


this will make redirected pages in the site work, but in the admin area this will make some problems;
and the problem is: when you are redirected in admin area, you will get an XML instead of the page,
so refreshing the page will get you to the right place.



2- /modules/system/templates/system_redirect.html

this is what your file should look like, this part is just like the previous part make us able to navigate while redirecting
throw Ajax:
<{php}>
if(isset(
$_GET['ajaxpage']) || isset($_POST['ajaxpage']) || true){
    
header("Content-type: text/xml; charset=UTF-8");
    echo 
'<?xml version="1.0" encoding="utf-8"?>';
    echo 
'<ajax-response>';
    echo 
'<response type="object" id="page">';
    echo 
'<page url="" title="" module="_nomodule_" time="'.$this->_tpl_vars['time'].'" href="'.urlencode($this->_tpl_vars['url']).'" >';
    echo 
'<content>';
    echo 
'<![CDATA[';
    echo 
'<div style="text-align:center; background-color: #EBEBEB; border-top: 1px solid #FFFFFF; border-left: 1px solid #FFFFFF; border-right: 1px solid #AAAAAA; border-bottom: 1px solid #AAAAAA; font-weight : bold;">';
    echo 
'<h4>'.$this->_tpl_vars['message'].'</h4>';
    echo 
'<p>'.$this->_tpl_vars['lang_ifnotreload'].'</p>';
    echo 
'</div>';
    if (
$this->_tpl_vars['xoops_logdump'] != ''){
    echo 
'<div>'.$this->_tpl_vars['xoops_logdump'].'</div>';
    }
    echo 
']]>';
    echo 
'</content>';
    echo 
'<dbug>';
    echo 
'<![CDATA[';
        <{/
php}>
        <!--{
xo-logger-output}-->
        <{
php}>
    echo 
']]>';
    echo 
'</dbug>';
    echo 
'</page>';
    echo 
'</response>';
    echo 
'</ajax-response>';
}else{
<{/
php}><html>
<
head>
<
meta http-equiv="Content-Type" content="text/html; charset=<{$xoops_charset}>" />
<
meta http-equiv="Refresh" content="<{$time}>; url=<{$url}>" />
<
title><{$xoops_sitename}></title>
<
link rel="stylesheet" type="text/css" media="all" href="<{$xoops_themecss}>" />
</
head>
<
body>
<
div style="text-align:center; background-color: #EBEBEB; border-top: 1px solid #FFFFFF; border-left: 1px solid #FFFFFF; border-right: 1px solid #AAAAAA; border-bottom: 1px solid #AAAAAA; font-weight : bold;">
  <
h4><{$message}></h4>
  <
p><{$lang_ifnotreload}></p>
</
div>
<{if 
$xoops_logdump != ''}><div><{$xoops_logdump}></div><{/if}>
</
body>
</
html><{php}>
}
<{/
php}>


just make sure the template is applied.

@Xguide:
yes you are right, protector module is needed, and this code is far from being used on a live site.
Thanks for your attention.

19
xguide
Re: an ajax aproach in theme
  • 2007/3/7 8:09

  • xguide

  • Just popping in

  • Posts: 43

  • Since: 2005/5/11


Damaster last work and get some usefulllinks and tips
here's a link about a starting point to fix some issues
we may found many others by testing scripts with 'Firebug'

http://wiki.script.aculo.us/scriptaculous/show/JSON

"As you can see, JSON couldn’t be much simplier and easy to use, but be aware that this method as is, is not the best solution keep in mind that it’s Java Script that get trough eval(), so be carefull. The Prototype library offer a method to parse json reponse, which does exacly the same thing as the script above.. It should not pose any security risks since the response, in theory, can only come from the same server from which the request was recieved, but sadly the theory and the real world are rarely the same. so better prevent than repair."

20
farshid
Re: an ajax aproach in theme
  • 2007/3/7 8:32

  • farshid

  • Just popping in

  • Posts: 34

  • Since: 2004/11/9


OK, I got what you mean, some how;
I want you to explain this a little bit more, cause I think an Ajax request could not call something out of its resided domain, correct me if I am wrong, what I have got from your post is that the problem here is the XML format used to send data which you suggest to be replaced with JSON, so please let me know what is the advantage of using JSON instead of XML, if your reasons are enough we will for sure make it work through JSON.

I will give JSON a try, I have not used it before but I know it is possible to use it with Rico and as you said it exists is prototype library; this way our next step will be to make these scripts work through JSON, not XML, If I have got what you mean we should out put page and blocks data via JSON... is that OK with you?
and do you think this will solve some problems?

I am waiting for any suggestions and data on the matter.

Login

Who's Online

178 user(s) are online (95 user(s) are browsing Support Forums)


Members: 0


Guests: 178


more...

Donat-O-Meter

Stats
Goal: $100.00
Due Date: Apr 30
Gross Amount: $0.00
Net Balance: $0.00
Left to go: $100.00
Make donations with PayPal!

Latest GitHub Commits