adrian

Page Protector

Recommended Posts

This module allows you and your site editors to protect a page (and optionally its children, grandchildren etc) from guest access directly from the page's Settings tab. You can also limit access to certain roles.

http://modules.processwire.com/modules/page-protector/

https://github.com/adrianbj/PageProtector

It makes it very easy for editors to set up various password protected areas on their site, or to simply protect a new page or section while they are still working on it.

  • Ability for your site editors to control the user access to pages directly from Settings tab of each page
  • Include whether to protect all children of this page or not
  • Optionally allow access to only specified roles
  • Option to protect all hidden pages (and optionally their children)
  • Ability to change the message on the login page to make it specific to this page
  • Option to have login form and prohibited message injected into a custom template
  • Access to the "Protect this Page" settings panel is controlled by the "page-edit-protected" permission
  • Table in the module config settings that lists the details all of the protected pages
  • Shortcut to protect entire site with one click

In addition to the admin interface, you can also set protection settings via the API:

// all optional, except "page_protected", which must be set to true/false
// if setting it to false, the other options are not relevant

$options = array(
    "page_protected" => true,
    "children_protected" => true,
    "allowed_roles" => array("role1", "role2"),
    "message_override" => "My custom login message",
    "prohibited_message" => "My custom prohibited access message"
);

$page->protect($options);

As alway, I would love any feedback / suggestions for improvements. Hope you find it useful!

Page Protection Settings (settings tab for each page)

post-985-0-73987600-1416875487_thumb.png

Module Config Settings

post-985-0-27882500-1416875500_thumb.png

  • Like 21

Share this post


Link to post
Share on other sites

Nice one Adrian! Minor suggestion, maybe add a note/description to the setting 'Protect children' that the protection cascades to grandchildren, etc. 

  • Like 2

Share this post


Link to post
Share on other sites

This is awesome. It's possible to set a protected page via API?

Glad you like it :)

Not currently possible - I didn't really think it would be that useful since this is primarily a tool for site editors. I am willing to add the option - perhaps a new protect method so you could do something like:

$page->protect($options);

where $options would be for children, message, roles, prohibited message.

Would you mind giving me a use case scenario so I can get a better idea of how useful this feature would be ?

  • Like 1

Share this post


Link to post
Share on other sites

In my social network this could be useful for users want to make some pages protected and decide who can view the page based on roles, for groups, pictures, or events etc....right now i make this with bare code, so having a module is always nicer and of course users can't go in admin panel so i need some api implementation :)

Share this post


Link to post
Share on other sites

Ok, I have committed a new version that supports protection via the API.

You can now do:

// all optional, except "page_protected", which must be set to true/false
// if setting it to false, the other options are not relevant

$options = array(
    "page_protected" => true,
    "children_protected" => true,
    "allowed_roles" => array("role1", "role2"),
    "message_override" => "My custom login message",
    "prohibited_message" => "My custom prohibited access message"
);

$page->protect($options);

Let me know if you have any problems.

EDIT: I am wondering if in your case dedicated code might be a better solution. This module stores the protection info in the module's data DB field. While this works great because there is no need for special fields to be added to the templates of a pages to be protected, I am worried you might come across some scaling issues if you have thousands or potentially millions of users, all wanting to protect various pages. I have no idea on the scale of your social network, but this is definitely something to consider. 

  • Like 4

Share this post


Link to post
Share on other sites

I'm probably missing something really obvious with this (php isn't my first language), but when I try to inject the form into a template all I get is an unknown variable warning for  $loginForm.

Share this post


Link to post
Share on other sites

I'm probably missing something really obvious with this (php isn't my first language), but when I try to inject the form into a template all I get is an unknown variable warning for  $loginForm.

Sorry you're having trouble.

All I can think is that you are trying to add it to a template that is not selected under the "Login Template" option in the config settings for this module. Are you trying to add it to an existing PW template file like home.php ?

The way this works is that the module uses the selected "Login Template" instead of the template that is normally used by a page.

Does that make sense / solve your problem?

Share this post


Link to post
Share on other sites

Trying to add it to the basic-page.php template, also selected this template in the "login template" section. I've managed to make it output the login boxes, but only them, nothing else in the source, just the styles and the login form. Even after logging in it still shows a missing variable error.

Share this post


Link to post
Share on other sites

Trying to add it to the basic-page.php template, also selected this template in the "login template" section. I've managed to make it output the login boxes, but only them, nothing else in the source, just the styles and the login form. Even after logging in it still shows a missing variable error.

Yeah, that's what I thought :)

That's not how this works. You need to create a dedicated template for the login form. Perhaps called: loginform.php

This template should only contain the framework of your site, eg the header and footer, like in the example, or however you like to structure things, along with $loginForm where you want it to appear.

This loginform.php template will be called instead of basic-page.php, home.php, etc if the page is protected and the person needs to login.

Does that make more sense now?

Share this post


Link to post
Share on other sites

I just added a couple of new options to this module that allow for automatic protection of unpublished and hidden pages and their children. I am finding the unpublished protection very handy as I can set the parent of a branch to unpublished while it is being developed. With this option enabled, I can send the link to this page direct to clients and they will be presented with the custom login form so they login and then immediately view the page - no need to go via the backend admin panel (just like the normal way this module works), and they won't get the 404 page if they attempt to visit when logged out. Because children can also be protected there is no worry about someone guessing the URL to subpages, the entire branch is protected based on the publication status of the parent. Once the branch is ready to be published, simply publish and it will be live and the protection is removed - no need to give clients access to the control of this module on the settings tab and explain how they work.

Hope you all find it useful!

  • Like 5

Share this post


Link to post
Share on other sites

Hi Adrian, the login template isn't working for me. I setup a custom template (login.php) and select it on the module settings, but the login form doesn't show. I'm using ProcessWire 3.0.3 devns.

login.php:

<?php include("./head.inc"); ?>

<div>
  <?php echo $loginForm; ?>
</div>

<?php include("./foot.inc"); ?>

Edit: When i disable the login template, the custom protected message isn't displaying either. The default "This page is protected. You must log in to view it." message is shown.
 

Share this post


Link to post
Share on other sites

Hi @Sanyaissues - sorry you are having problems. I can replicate the problem with the custom template not working in PW 3.0, but aren't seeing the issue with the custom protected message not working - make sure you are editing the message on the Settings tab of the protected page.

Now back to the custom template problem - do you have debug mode turned on in your config.php file? Do you then see this error: 

Notice: Undefined variable: loginForm in /pathto/site/templates/login.php on line 4

The problem seems to be passing variables using wireRenderFile. It works fine in PW 2.x, but looks like there might be a problem in PW 3.x

Can you please confirm that this is the error you are getting.

I am not really at my computer again fully for another a couple of weeks, but I will try to help figure this out.

Anyone else out there reading this that has seen any problems with passing variables using wireRenderFile in PW 3.x?

Share this post


Link to post
Share on other sites

Hi @adrian thanks for your response. As you say, i get the undefined variable error.

About the custom protected message isn't working. I save a new one but isn't rendering on the front-end. This is what i get:

 <form class='PageProtectorForm' action='./' method='post'>
    <legend></legend>
    <input type='text' name='username' placeholder='Username'>
    <input type='password' name='pass' placeholder='Password'>
    <p><button type='submit' name='login'>Login</button></p>
  </form>

Share this post


Link to post
Share on other sites
Hi @adrian thanks for your response. As you say, i get the undefined variable error.

It was a bug with the File Compiler in PW 3.x - it has been fixed in today's commits to the devns branch.

About the custom protected message isn't working. I save a new one but isn't rendering on the front-end. This is what i get:

That does seem weird - the custom message should be between the <legend> tags. Can you provide a screenshot of the settings tab for the page in question?

Share this post


Link to post
Share on other sites

You need to change the custom message on the Settings tab of the Home page. 

The message on the module settings page should populate newly added protected pages, but once a page has been protected, it stores its custom message separately.

Let me know if you still have problems.

I assume that the login template option is now working for you with the latest PW 3.x build?

Share this post


Link to post
Share on other sites
The login template option isn't working on 3.0.4

Have you cleared the compiled templates? 

Modules > Site > Clear Compiled Files

I think the error you are seeing is from a cached compiled template from before the problem was fixed in 3.0.4

Share this post


Link to post
Share on other sites

I read all over the docs and the forum about protecting certain pages from access and wonder why my efforts are unsuccessful.

The situation (simplified):

Pages tree

Home
 -   Free Stuff
     - -   Free1
     - -   Free2
 -  Private Stuff
    - -  Private1
    - -  Private2
       
Free Stuff and its children have the template "standard"; Access managing is set to No.  
Private Stuff and its children have the template "private": in its Access settings the page view option is unticked for the guest role.
 
Apart from superuser and guest there are the following roles:
    editor
    member

The editor role grants page edit permission for all the pages.
Users having the member role have to log in to get acces to the private pages.

Now my question:

What do I have to do to give the member users page view access exclusively for the private pages?
(That is, they should not see the pages of template standard.)

What I tried: In the Settings of the page Free Stuff I ticked Protect this page, then Protect children too.
As Allowed roles I selected all but the role member.

So I expected that a member user would no longer have access to the Full Stuff page nor its children. But that doesn't work.

Maybe I'm missing something obvious. Any help is hihgly appreciated!

Share this post


Link to post
Share on other sites
What I tried: In the Settings of the page Free Stuff I ticked Protect this page, then Protect children too.

As Allowed roles I selected all but the role member.

So I expected that a member user would no longer have access to the Full Stuff page nor its children. But that doesn't work.

It sounds like you are using the PageProtector module. It only prevents users from viewing pages on the front-end. I can't tell if that's what you want or if you expect them to also not be able to view and edit them in the backend?

Also, you say that you selected all roles, except the member role. Do the members also have one of the other selected roles? Including "guest"?

  • Like 1

Share this post


Link to post
Share on other sites

Thank you, adrian.

Yes, I'm using the PageProtector module (forgot to mention it).

Members get only page view, not page edit permission. They should not have access to the backend.*

Members have the roles "members" and "guest" - you can't remove the guest role from a user. They don't have any of the roles with page edit permission.

*Edit: This doesn't work - they have access to the pages tree (not wanted), but see just the view buttons.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Robin S
      Some introduction...
      This module is experimental and there are probably bugs - so treat it as alpha and don't use it on production websites.
      I started on this module because there have been quite a few requests for "fake" or "invisible" parent functionality and I was curious about what is possible given that the idea sort of goes against the PW page structure philosophy. I'm not sure that I will use this module myself, just because I don't really see a long list of pages under Home (or anywhere else) as untidy or cluttered. I would tend to use Lister Pro when I want to see some set of pages as a self-contained group. But maybe others will find it useful.
      At the moment this module does not manipulate the breadcrumb menu in admin. So when you are editing or adding a virtual child the real location of the page is revealed in the breadcrumb menu. That's because I don't see the point in trying to comprehensively fool users about the real location of pages - I think it's better that they have some understanding of where the pages really are. But I'm open to feedback on this and it is possible to alter the breadcrumbs if there's a consensus that it would be better that way.
       
      Virtual Parents
      Allows pages in Page List to be grouped under a virtual parent.
      This module manipulates the page list and the flyout tree menu to make it appear that one or more pages are children of another page when in fact they are siblings of that page.
      Why would you do that instead of actually putting the child pages inside the parent? Mainly if you want to avoid adding the parent name as part of the URL. For example, suppose you have some pages that you want to be accessed at URLs directly off the site root: yourdomain.com/some-page/. But in the page list you want them to be appear under a parent for the sake of visual grouping or to declutter the page list under Home.
      Example of how the page structure actually is

      Example of how the page structure appears with Virtual Parents activated

      How it works
      This module identifies the virtual parents and virtual children by way of template. You define a single template as the virtual parent template and one or more templates as the virtual child templates. Anytime pages using the child template(s) are siblings of a page using the parent template, those child pages will appear as children of the virtual parent in the page list and tree menu.
      You will want to create dedicated templates for identifying virtual parents and virtual children and reserve them just for use with this module.
      Features
      Adjusts both page list and tree flyout menu to show the virtual parent/child structure, including the count of child pages. Works everywhere page list is used: Page List Select / Page List Select Multiple (and therefore CKEditor link dialog). Intercepts the "Add page" process in admin, so that when an attempt is made to add a child to a virtual parent, the child is added where it belongs (the next level up) and the template selection is limited to virtual child templates. Intercepts moving and sorting pages in the page list, to ensure only virtual children may be moved/sorted under the virtual parent. Superusers have a toggle switch at the bottom of the page list to easily disable/enable Virtual Parents in order to get a view of what the real page structure is. Usage
      Install the Virtual Parents module.
      In the module config, enter pairs of parent/child template names in the form virtual_parent_template=virtual_child_template. If needed you can specify multiple pipe-separated child templates: virtual_parent_template=child_template_1|child_template_2. One pair of template names per line.
      There is a checkbox in the module config to toggle Virtual Pages on and off, but it's more convenient to use this from the page list.
      Notes
      It's important to keep in mind the real location of the virtual child pages. This module is only concerned with adjusting the appearance of page list and tree menu for the sake of visual grouping and tidiness. In all other respects the virtual children are not children of the virtual parent at all.
      It's recommended to select an icon for the virtual parent template (Advanced tab) so virtual parents are marked out in the page list as being different from normal parent pages.
      Do not place real children under a virtual parent. There is some protection against this when moving pages in the page list, but when it comes to changing a page's parent via the Settings tab the only protection is common sense.
       
      https://github.com/Toutouwai/VirtualParents
    • By horst
      Wire Mail SMTP

      An extension to the new WireMail base class that uses SMTP-transport

      This module integrates EmailMessage, SMTP and SASL php-libraries from Manuel Lemos into ProcessWire. I use this continously evolved libraries for about 10 years now and there was never a reason or occasion not to do so. I use it nearly every day in my office for automated composing and sending personalized messages with attachments, requests for Disposition Notifications, etc. Also I have used it for sending personalized Bulkmails many times.

      The WireMailSmtp module extends the new email-related WireMail base class introduced in ProcessWire 2.4.1 (while this writing, the dev-branch only).
       
      Here are Ryans announcement.



      Current Version 0.2.7
      get it from the Modules Directory Install and Configure

      Download the module into your site/modules/ directory and install it.

      In the config page you fill in settings for the SMTP server and optionaly the (default) sender, like email address, name and signature.
      You can test the smtp settings directly there. If it says "SUCCESS! SMTP settings appear to work correctly." you are ready to start using it in templates, modules or bootstrap scripts.


      Usage Examples
      The simplest way to use it:
      $numSent = wireMail($to, $from, $subject, $textBody); $numSent = wireMail($to, '', $subject, $textBody); // or with a default sender emailaddress on config page This will send a plain text message to each recipient.
       
      You may also use the object oriented style:
      $mail = wireMail(); // calling an empty wireMail() returns a wireMail object $mail->to($toEmail, $toName); $mail->from = $yourEmailaddress; // if you don't have set a default sender in config // or if you want to override that $mail->subject($subject); $mail->body($textBody); $numSent = $mail->send(); Or chained, like everywhere in ProcessWire:
      $mail = wireMail(); $numSent = $mail->to($toEmail)->subject($subject)->body($textBody)->send(); Additionaly to the basics there are more options available with WireMailSmtp. The main difference compared to the WireMail BaseClass is the sendSingle option. With it you can set only one To-Recipient but additional CC-Recipients.
      $mail = wireMail(); $mail->sendSingle(true)->to($toEmail, $toName)->cc(array('person1@example.com', 'person2@example.com', 'person3@example.com')); $numSent = $mail->subject($subject)->body($textBody)->send(); The same as function call with options array:
      $options = array( 'sendSingle' => true, 'cc' => array('person1@example.com', 'person2@example.com', 'person3@example.com') ); $numSent = wireMail($to, '', $subject, $textBody, $options); There are methods to your disposal to check if you have the right WireMail-Class and if the SMTP-settings are working:
      $mail = wireMail(); if($mail->className != 'WireMailSmtp') { // Uups, wrong WireMail-Class: do something to inform the user and quit echo "<p>Couldn't get the right WireMail-Module (WireMailSmtp). found: {$mail->className}</p>"; return; } if(!$mail->testConnection()) { // Connection not working: echo "<p>Couldn't connect to the SMTP server. Please check the {$mail->className} modules config settings!</p>"; return; } Following are a ...


      List of all options and features


      testConnection () - returns true on success, false on failures


      sendSingle ( true | false ) - default is false

      sendBulk ( true | false ) - default is false, Set this to true if you have lots of recipients (50+)


      to ($recipients) - one emailaddress or array with multiple emailaddresses

      cc ($recipients) - only available with mode sendSingle, one emailaddress or array with multiple emailaddresses

      bcc ($recipients) - one emailaddress or array with multiple emailaddresses

       
      from = 'person@example.com' - emailaddress, can be set in module config (called Sender Emailaddress) but it can be overwritten here

      fromName = 'Name Surname' - optional, can be set in module config (called Sender Name) but it can be overwritten here


      priority (3) - 1 = Highest | 2 = High | 3 = Normal | 4 = Low | 5 = Lowest

      dispositionNotification () or notification () - request a Disposition Notification


      subject ($subject) - subject of the message

      body ($textBody) - use this one alone to create and send plainText emailmessages

      bodyHTML ($htmlBody) - use this to create a Multipart Alternative Emailmessage (containing a HTML-Part and a Plaintext-Part as fallback)

      addSignature ( true | false ) - the default-behave is selectable in config screen, this can be overridden here
      (only available if a signature is defined in the config screen)

      attachment ($filename, $alternativeBasename = "") - add attachment file, optionally alternative basename


      send () - send the message(s) and return number of successful sent messages


      getResult () - returns a dump (array) with all recipients (to, cc, bcc) and settings you have selected with the message, the message subject and body, and lists of successfull addresses and failed addresses,


      logActivity ($logmessage) - you may log success if you want

      logError ($logmessage) - you may log warnings, too. - Errors are logged automaticaly
       
       
      useSentLog (true | false) - intended for usage with e.g. third party newsletter modules - tells the send() method to make usage of the sentLog-methods - the following three sentLog methods are hookable, e.g. if you don't want log into files you may provide your own storage, or add additional functionality here

      sentLogReset ()  - starts a new LogSession - Best usage would be interactively once when setting up a new Newsletter

      sentLogGet ()  - is called automaticly within the send() method - returns an array containing all previously used emailaddresses

      sentLogAdd ($emailaddress)  - is called automaticly within the send() method
       
      Changelog: https://github.com/horst-n/WireMailSmtp/blob/master/CHANGELOG.md
       
    • By ukyo
      Call ProcessWire API Functions Inside STRING
      Github Repo
      Current status : BETA
      Each called method must return string value !
      I added all functions, but not tested all. I focused page(), page()->render and field properties (label, description and notes). I also tested some basic pages() api calls.
      Your API calls must start with { and must end with }. For use multiple arguments inside functions, separate arguments with ~ char.
      NOTE If you pass directly arguments to api {page(title)}, this call will check for requestedApiCall()->get(arguments).
      USAGE
      processString(string, page, language); Get page title <?php $str = "You are here : {page:title}"; echo processString($str); ?> Get page children render result <?php $str = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<hr>{page:render:children}"; echo processString($str); ?> Get homepage title <?php $str = "You can visit our <a hre='{pages(1):url}'>{pages:get(1):title}</a>"; echo processString($str); ?> Get title field label, description or notes <?php $str = "Our title field properties are : label: {label(title)} - description: {description(title)} - notes: {notes(title)}"; echo processString($str); ?> Multiple examples <?php $str = " <ul class='uk-list uk-list-striped'> <li><b>01: GET FIELD LABEL</b> <code>&#123;label(title)&#125;</code> <b>RESULT :</b> <code>{label(title)}</code></li> <li><b>02: GET FIELD LABEL WITH PREFIX</b> <code>&#123;label(title~=> )&#125;</code> <b>RESULT :</b> <code>{label(title~=> )}</code></li> <li><b>03: GET FIELD LABEL WITH SUFFIX</b> <code>&#123;label(title~~ <=)&#125;</code> <b>RESULT :</b> <code>{label(title~~ <=)}</code></li> <li><b>04: GET FIELD DESCRIPTION</b> <code>&#123;description(title)&#125;</code> <b>RESULT :</b> <code>{description(title)}</code><br> <li><b>05: GET FIELD DESCRIPTION WITH PREFIX</b> <code>&#123;description(title~=> )&#125;</code> <b>RESULT :</b> <code>{description(title~=> )}</code></li> <li><b>06: GET FIELD DESCRIPTION WITH SUFFIX</b> <code>&#123;description(title~~ <=)&#125;</code> <b>RESULT :</b> <code>{description(title~~ <=)}</code></li> <li><b>07: GET FIELD NOTES</b> <code>&#123;notes(title)&#125;</code> <b>RESULT :</b> <code>{notes(title)}</code><br> <li><b>08: GET FIELD NOTES WITH PREFIX</b> <code>&#123;notes(title~=> )&#125;</code> <b>RESULT :</b> <code>{notes(title~=> )}</code></li> <li><b>09: GET FIELD NOTES WITH SUFFIX</b> <code>&#123;notes(title~~ <=)&#125;</code> <b>RESULT :</b> <code>{notes(title~~ <=)}</code></li> <li><b>10: GET PAGE TITLE</b> <code>&#123;page(title)&#125;</code> <b>RESULT :</b> <code>{page(title)}</code></li> <li><b>11: GET PAGE TITLE</b> <code>&#123;page:title&#125;</code> <b>RESULT :</b> <code>{page:title}</code></li> <li><b>12: GET PAGE RENDER TITLE</b> <code>&#123;page:render:title&#125;</code> <b>RESULT :</b> <code>{page:render:title}</code></li> <li><b>12: GET HOMEPAGE TITLE</b> <code>&#123;pages:get(template=home):title&#125;</code> <b>RESULT :</b> <code>{pages:get(template=home):title}</code></li> <li><b>13: GET HOMEPAGE TEMPLATE ID</b> <code>&#123;pages:get(template=home):template:id&#125;</code> <b>RESULT :</b> <code>{pages:get(template=home):template:id}</code></li> </ul> "; echo processString($str); ?>
    • By Robin S
      This module corrects a few things that I find awkward about the "Add New Template" workflow in the PW admin. I opened a wishlist topic a while back because it would good to resolve some of these things in the core, but this module is a stopgap for now.
      Originally I was going to share these as a few standalone hooks, but decided to bundle them together in a configurable module instead. This module should be considered alpha until it has gone through some more testing.
      Add Template Enhancements
      Adds some efficiency enhancements when adding or cloning templates via admin.

      Features
      Derive template label from name: if you like to give each of your templates a label then this feature can save some time. When one or more new templates are added in admin a label is derived automatically from the name. There are options for underscore/hyphen replacement and capitalisation of the label. Edit template after add: when adding only a single template, the template is automatically opened for editing after it is added. Copy field contexts when cloning: this copies the field contexts (a.k.a. overrides such as column width, label and description) from the source template to the new template when using the "Duplicate/clone this template?" feature on the Advanced tab. Copy field contexts when duplicating fields: this copies the field contexts if you select the "Duplicate fields used by another template" option when adding a new template. Usage
      Install the Add Template Enhancements module.
      Configure the module settings according to what suits you.
       
      https://github.com/Toutouwai/AddTemplateEnhancements
    • By AAD Web Team
      Hi,
      I've put in a support request (as a followup on an existing one) for this but it's nearly 10pm Ryan's time, so I thought I'd ask on here just in case someone can help...
      Yesterday we purchased ProDrafts, but I couldn't get the key to validate. Every time I hit submit on the module settings screen the key would be removed from the field I entered it in, and then it would complain about the missing value. I put in a support request and Ryan responded last night. It turned out it was because we're behind a proxy/firewall. He gave me a fix to get around that issue - some code to go into admin.php. I put that code in and saved admin.php, but now I can't even get into our admin anymore!
      (Just to clarify, I took the code back out and saved admin.php but that made no difference. It's definitely not the new code causing the error.)
      The errors relate to a lack of permission on the ProDrafts module (see attached screenshot). We do have a key, but evidently the code Ryan gave me to add the key in via admin.php isn't taking effect before the error is thrown...?
      I tried removing the ProDrafts directory from the modules directory, but that hasn't helped.
      Is there a hook I can put in somewhere to tell it not to load ProDrafts at all, or not check the permissions? Or is there some way to manually uninstall it from the file system?
      Thanks!
      Margaret