- Widget.Chmod-0.3

Documentation | Source

NAME

Widget.Chmod - Permission configurator widget

SYNOPSIS

   <form action="config.pl">
   <div id="chmod_inject"><!-- this will hold the widget --></div>
   <script type="text/javascript">
   Widget.Chmod.chmod({
      value : '0755',     // set chmod value (can also be 755)
      ch1   : 'my_fname', // octal file mode input
      ch2   : 'my_fname2' // text file mode input
   });
   </script>
   <noscript>
   <input type="text" name="chmodval1" value="755">
   </noscript>
   </form>

DESCRIPTION

Widget.Chmod will generate a widget for chmod settings in octal notation. This may be useful for configuration screens.

FUNCTIONS

chmod

This function is importable via JSAN import mechanism.

Parameters

You can alter the interface with setting several parameters.

  • ch1
  • The name of the first chmod input field (numerical input).

  • ch2
  • The name of the second chmod input field (string input).

  • injectid
  • The id of the injection area (you have to set this, if it is not chmod_inject).

  • size
  • The size of the input fields. Default is 10.

  • disable
  • Chmod input areas are disable by default. If you want to enable them, pass this parameter with a false value.

  • rtl
  • If enabled, the widget will have a right-to-left orientation. Disabled by default.

  • Textual input part of the widget assumes that you are configuring a regular file. If the target is a directory or something else, you may need to set one of these parameters to a true value:
  •    Parameter   Meaning
       ---------   -------
       is_dir      File is a directory
       is_block    File is a block special file
       is_char     File is a character special file
       is_sym      File is a symbolic link
       is_pipe     File is a named pipe
       is_sock     File is a domain socket
  • The module interface can be translated into other languages (i18n) via setting several parameters. Available parameters are explained in the table below:
  •    Parameter   Default Value
       ---------   -------------
          u        User
          g        Group
          o        Other
          r        Read
          w        Write
          x        Execute

SEE ALSO

Widget.Timer.

CAVEATS

  • chmod.inject() will use document.write() instead of altering .innerHTML() if you are using (I hope you are doing this only for nostalgia) Netscape 4.x.
  • Saying this, you can guess that this library is compatible with NS4 at a certain degree.

  • throw() is used if something fails. You may have to wrap your code inside a try/catch block to catch exceptions:
  •    try {
          Widget.Chmod.chmod({ value : '0755' });
       } catch (e) {
              alert( "Something very bad has happened: " + e.message );
       }
  • throw() can not be used in Netscape Navigator 4.x. So, you'll only get an information box under this archaic software.
  • The widget looks terrible under Netscape Navigator 4.x (if this is a problem for you).
  • If you enable the input boxes and change their values, the change in values will not be tracked (i.e.: the checkboxes will not change dynamically). This feature is currently not implemented.

BUGS

Contact the author if you find any.

This library is tested with: Opera 9.10, MSIE 6.0, Netscape Communicator 4.77, and Mozilla FireFox 2.0.0.1 under Windows XP Professional SP2.

AUTHOR

Burak Gürsoy <burak@cpan.org>

COPYRIGHT

Copyright 2007 Burak Gürsoy. All rights reserved.

LICENSE

This library is free software; you can redistribute it and/or modify it under the terms of the "Artistic License": http://dev.perl.org/licenses/artistic.html.

// Widget.Chmod by Burak G�rsoy <burak[at]cpan[dot]org>
if (!Widget) var Widget = {};

Widget.Chmod = function ( o ) {
   this.init( o );
}

Widget.Chmod.VERSION   = '0.3';
Widget.Chmod.EXPORT_OK = ['chmod'];
Widget.Chmod.COUNTER   = 0;
Widget.Chmod.DEFAULTS  = {
   // field ids
   'por'     : 'chmod_or',
   'pow'     : 'chmod_ow',
   'pox'     : 'chmod_ox',

   'pgr'     : 'chmod_gr',
   'pgw'     : 'chmod_gw',
   'pgx'     : 'chmod_gx',

   'ppr'     : 'chmod_pr',
   'ppw'     : 'chmod_pw',
   'ppx'     : 'chmod_px',

   'ch1'     : 'chmodval1',
   'ch2'     : 'chmodval2',

   'injectid': 'chmod_inject',

   // style elements
   'size'    : 10,
   'disable' :  1,
   'rtl'     :  0,

   // i18n
   'u'       : 'User',
   'g'       : 'Group',
   'o'       : 'Other',
   'r'       : 'Read',
   'w'       : 'Write',
   'x'       : 'Execute'
};

// protect private object properties
Widget.Chmod.FORBIDDEN  = {
   'IS_DUMB'  : 1,
   'FATAL'    : 1,
   'IS_FATAL' : 1
};

Widget.Chmod.chmod = function ( o ) {
   var id   = 'WidgetChmod' + Widget.Chmod.COUNTER++;
   var CODE = id + " = new Widget.Chmod ( o );"
            + id + '.setid( "' + id + '" );'
            + id + '.inject();'
            + id + '.display();'
            ;
   eval(CODE);
}

Widget.Chmod.prototype.init = function ( o ) {
   var all = document.all;
   var id  = document.getElementById;
   this.IS_DUMB  =  all &&  id      ? 0  //IE5
                 :  all && !id      ? 0  //IE4
                 : !all &&  id      ? 0  //NS6
                 :  document.layers ? 1  //NS4
                 :                    1; //??
   this.FATAL    = "[ Widget.Chmod fatal error ]\n\n";
   this.IS_FATAL = 0;
   if ( o && typeof o == 'object' ) {
      this.value = '';
      for ( key in o ) {
	     if ( Widget.Chmod.FORBIDDEN[key] || (this[key] && typeof this[key] == 'function') ) {
	        return this._fatality(
				      "You have tried to set a private option via constructor."
			         +" Access denied for " + key
			       );
	     }
	     this[key] = o[key];
      }
   }
   if ( this.value ) {
      this.value = this._clean(this.value);
   }
   else {
      return this._fatality("Chmod value is not set");
   }
}

Widget.Chmod.prototype.setid = function ( id ) {
   if ( id ) this.ID = id;
}

Widget.Chmod.prototype.control = function () {
   // controls the value of visual representations (input boxes)
   var o = this._fetch();
   if( !o.ch1.value ) return;

   var t  = 0;
   var sn = this['is_dir'  ] ? 'd'  // directory
          : this['is_block'] ? 'b'  // block special file
          : this['is_char' ] ? 'c'  // character special file
          : this['is_sym'  ] ? 'l'  // symbolic link
          : this['is_pipe' ] ? 'p'  // named pipe
          : this['is_sock' ] ? 's'  // domain socket
          :                    '-'  // regular file
          ;

   if( o.por.checked ) { t += 400; sn += 'r' } else { sn += '-' }
   if( o.pow.checked ) { t += 200; sn += 'w' } else { sn += '-' }
   if( o.pox.checked ) { t += 100; sn += 'x' } else { sn += '-' }

   if( o.pgr.checked ) { t +=  40; sn += 'r' } else { sn += '-' }
   if( o.pgw.checked ) { t +=  20; sn += 'w' } else { sn += '-' }
   if( o.pgx.checked ) { t +=  10; sn += 'x' } else { sn += '-' }

   if( o.ppr.checked ) { t +=   4; sn += 'r' } else { sn += '-' }
   if( o.ppw.checked ) { t +=   2; sn += 'w' } else { sn += '-' }
   if( o.ppx.checked ) { t +=   1; sn += 'x' } else { sn += '-' }

   o.ch1.value = t;  // numeric input
   o.ch2.value = sn; // text input
   if( this._is_disabled() ) o.ch1h.value = t;
}

Widget.Chmod.prototype.display = function ( n ) {
   if ( this.IS_FATAL ) return;
   var o   = this._fetch();
   var val = o.ch1.value;
   if ( !val ) return;
   var e = val.split('');
   switch ( val.length ) {
      case 1:
         this._check( e[0], o.ppr, o.ppw, o.ppx );
         break;
      case 2:
         this._check( e[0], o.pgr, o.pgw, o.pgx );
         this._check( e[1], o.ppr, o.ppw, o.ppx );
         break;
      case 3:
         this._check( e[0], o.por, o.pow, o.pox );
         this._check( e[1], o.pgr, o.pgw, o.pgx );
         this._check( e[2], o.ppr, o.ppw, o.ppx );
         break;
      default:
         return this._fatality(
			       "Initialization failed. Bogus chmod value: "
			       + o.ch1.value
			    );
         break;
   }
   this.control();
}

Widget.Chmod.prototype._fatality = function ( message ) {
   alert( this.FATAL + message );
   this.IS_FATAL = 1;
   if ( this.IS_DUMB ) {
      return;
   }
   else {
      eval( 'throw message' ); // to fool NS4x
   }
}

Widget.Chmod.prototype._param = function ( name ) {
   if( !name ) return;
   var o = document.all            ? document.all[name]
         : document.getElementById ? document.getElementById(name)
         : document.layers         ? this._nsparam(name)
         :                           {};
   return o;
}

Widget.Chmod.prototype._nsparam = function ( name ) {
   var object = document.layers[name];
   if ( !object ) {
      for( var i = 0; i < document.forms.length; i++ ) { // is_form()
         if( !document.forms[i] ) break;
         object = eval( 'document.forms[' + i + '].' + name );
         if( object ) break;
      }
   }
   return object;
}

Widget.Chmod.prototype._pfix = function () {
   var pfix = this['injectid'] || Widget.Chmod.DEFAULTS['injectid'] || '';
   return pfix;
}

Widget.Chmod.prototype._fetch = function () {
   var d    = Widget.Chmod.DEFAULTS;
   var pfix = this._pfix();
   var obj  = {
      'por' : this._param( pfix + ( this['por'] || d['por'] ) ),
      'pow' : this._param( pfix + ( this['pow'] || d['pow'] ) ),
      'pox' : this._param( pfix + ( this['pox'] || d['pox'] ) ),
      'pgr' : this._param( pfix + ( this['pgr'] || d['pgr'] ) ),
      'pgw' : this._param( pfix + ( this['pgw'] || d['pgw'] ) ),
      'pgx' : this._param( pfix + ( this['pgx'] || d['pgx'] ) ),
      'ppr' : this._param( pfix + ( this['ppr'] || d['ppr'] ) ),
      'ppw' : this._param( pfix + ( this['ppw'] || d['ppw'] ) ),
      'ppx' : this._param( pfix + ( this['ppx'] || d['ppx'] ) ),
      'ch2' : this._param( pfix + ( this['ch2'] || d['ch2'] ) ),
      'ch1' : this._param(          this['ch1'] || d['ch1']   ),
      'ch1h': ''
   };
   if ( this._is_disabled() ) {
	  var ch1name = this['ch1'] || d['ch1'];
      obj['ch1h'] = this._param( ch1name + '_disabled' );
   }
   return obj;
}

Widget.Chmod.prototype._clean = function ( n ) {
   if( !n ) return n;
   return n.replace(/^0/, '');
}

Widget.Chmod.prototype._check = function ( bits, r, w, x ) {
   // display() uses a switch() block and make calls to _check()
   // this multiple switch()es seems to confuse firefox' js engine
   // since, using switch() here, breaks the code under Firefox 2x
   // however, IE & Opera works fine. even NS Navigator 4.77 is ok.
   // dumb Firefox :p
        if ( bits == 7 ) { r.checked = 1; w.checked = 1; x.checked = 1; } //rwx
   else if ( bits == 6 ) { r.checked = 1; w.checked = 1;                } //rw-
   else if ( bits == 5 ) { r.checked = 1;                x.checked = 1; } //r-x
   else if ( bits == 4 ) { r.checked = 1;                               } //r--
   else if ( bits == 3 ) {                w.checked = 1; x.checked = 1; } //-wx
   else if ( bits == 2 ) {                w.checked = 1;                } //-w-
   else if ( bits == 1 ) {                               x.checked = 1; } //--x
   else                  {                                              }
}

Widget.Chmod.prototype._is_disabled = function () {
   var d       = Widget.Chmod.DEFAULTS;
   var disable = typeof this['disable'] != 'undefined'
               ?        this['disable']
               :           d['disable'];
   return disable;
}

Widget.Chmod.prototype.inject = function () {
   if ( this.IS_FATAL ) return;
   var pfix      = this._pfix();
   var d         = Widget.Chmod.DEFAULTS;
   var rtl       = this[ 'rtl'] || d['rtl'] || 0;
   var disable   = this._is_disabled();
   var style     = this._get_style();
   var ch1name   = this['ch1' ] || d['ch1' ];
   var ch2name   = this['ch2' ] || d['ch2' ];
   var size      = this['size'] || d['size'];
   var ch1hidden = ch1name;
   if (disable)
   ch1name      += '_disabled';
   var input     = { num : '', str : '' };
   input.num    += ' <input';
   input.num    += ' type  = "text"';
   input.num    += ' name  = "' + ch1name       + '"';
   input.num    += ' id    = "' + ch1name       + '"';
   input.num    += ' value = "' + this['value'] + '"';
   input.num    += ' size  = "' + size          + '"';
   if(disable)
   input.num    += ' disabled="disabled"';
   input.num    += style;
   input.num    += ' /> ';

   input.str    += ' <input';
   input.str    += ' type  = "text"';
   input.str    += ' name  = "' + pfix + (this['ch2'  ] || d['ch2' ]) + '"';
   input.str    += ' id    = "' + pfix + (this['ch2'  ] || d['ch2' ]) + '"';
   input.str    += ' value = ""';
   input.str    += ' size  = "' + size + '"';
   if(disable)
   input.str    += ' disabled="disabled"';
   input.str    += style;
   input.str    += ' /> ';

   if(disable) {
      input.str += '<input';
      input.str += ' type  = "hidden"';
      input.str += ' name  = "' + ch1hidden     + '"';
      input.str += ' id    = "' + ch1hidden     + '"';
      input.str += ' value = "' + this['value'] + '"';
      input.str += ' />';
   }

   var html    = '';
   html += '<table border="0">';
   html += '<tr>';
   html += '<td colspan="3"' + style + '>';
   html += rtl ? input.str + input.num : input.num + input.str;
   html += '</td></tr><tr>';
   html += '<td>' + this._injectf( 'u', 'por', 'pow', 'pox' ) + '</td>';
   html += '<td>' + this._injectf( 'g', 'pgr', 'pgw', 'pgx' ) + '</td>';
   html += '<td>' + this._injectf( 'o', 'ppr', 'ppw', 'ppx' ) + '</td>';
   html += '</tr></table>';
   this.IS_DUMB ? document.write( html ) : this._injection( html );
}

Widget.Chmod.prototype._injection = function ( html ) {
   var d = Widget.Chmod.DEFAULTS;
   var n = this['injectid'] || d['injectid'];
   var o = this._param(n);
   if( !o ) return;
   o.innerHTML = html;
}

Widget.Chmod.prototype._get_style = function () {
   if ( this.IS_DUMB ) return '';
   var d   = Widget.Chmod.DEFAULTS;
   var rtl = this['rtl'] || d[ 'rtl'] || 0;
   return rtl ? ' style="text-align:right"' : '';
}

Widget.Chmod.prototype._injectf = function ( title, r, w, x ) {
   var pfix  = this._pfix();
   var d     = Widget.Chmod.DEFAULTS;
   var rtl   = this[ 'rtl'  ] || d[ 'rtl'  ] || 0;
   var style = this._get_style();
   var td    = '<td'+style+'>';
   var id    = {
      'r' : this[ r ] || d[ r ],
      'w' : this[ w ] || d[ w ],
      'x' : this[ x ] || d[ x ]
   };
   var lang = {
      'r' : this['r'] || d['r'],
      'w' : this['w'] || d['w'],
      'x' : this['x'] || d['x']
   };
   var label = {
      'r' : td + ' <label for="' + pfix + id.r + '" title="' + lang.r + '">' + lang.r + '</label> </td>',
      'w' : td + ' <label for="' + pfix + id.w + '" title="' + lang.w + '">' + lang.w + '</label> </td>',
      'x' : td + ' <label for="' + pfix + id.x + '" title="' + lang.x + '">' + lang.x + '</label> </td>'
   };

   label['rr'] = rtl ? label.r : '';
   label['rw'] = rtl ? label.w : '';
   label['rx'] = rtl ? label.x : '';
   label['lr'] = rtl ? ''      : label.r;
   label['lw'] = rtl ? ''      : label.w;
   label['lx'] = rtl ? ''      : label.x;
   var title   = this[title] || d[title];
   var input   = '<input type="checkbox" name="';
   var onclick = '" onclick="' + this.ID + '.control()" /> ';
   var html    = '<table border="0" cellpadding="0" cellspacing="0">';
       html   += '<tr>' + label.rr + td + input + pfix + id.r + '" id="' + pfix + id.r + onclick + '</td>' + label.lr + "</tr>\n";
       html   += '<tr>' + label.rw + td + input + pfix + id.w + '" id="' + pfix + id.w + onclick + '</td>' + label.lw + "</tr>\n";
       html   += '<tr>' + label.rx + td + input + pfix + id.x + '" id="' + pfix + id.x + onclick + '</td>' + label.lx + "</tr>\n";
       html   += '</table>';
       html    = '<fieldset>' + '<legend>' + title + '</legend>' + html + '</fieldset>';
   if(rtl)
       html    = '<div style="text-align:right">' + html + '</div>';
   return html;
}

/*

*/