home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libpics / picsapi.c < prev   
Encoding:
C/C++ Source or Header  |  1998-04-08  |  14.8 KB  |  665 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*
  19.  * Glue code to make PICS work in the client.  This is just a thin
  20.  * layer between the W3C code and our layout engine to digest PICS labels.
  21.  * Coded by Lou Montulli
  22.  */
  23.  
  24. #include "xp.h"
  25. #include "cslutils.h"
  26. #include "csll.h"
  27. #include "csllst.h"
  28. #include "pics.h"
  29. #include "prefapi.h"
  30. #include "xpgetstr.h"
  31. #include "sechash.h"
  32. #include "base64.h"
  33.  
  34. extern int XP_ALERT_PROMPT_JAVA_CAPIBILITIES_PASSWORD;
  35. extern int XP_ALERT_PROMPT_JAVA_CAPIBILITIES_PASSWORD_FAILED_ONCE;
  36.  
  37. typedef struct {
  38.     PICS_RatingsStruct * rs;
  39.     XP_Bool rs_invalid;
  40. } ClosureData;
  41.  
  42. PRIVATE StateRet_t 
  43. target_callback(CSLabel_t *pCSLabel,
  44.         CSParse_t * pCSParse,
  45.          CSLLTC_t target, XP_Bool closed,
  46.          void * pClosure)
  47. {
  48.     char * ratingname;
  49.     char * ratingstr;
  50.     ClosureData *cd = (ClosureData *)pClosure;
  51.     
  52.     /* closed signifies that the parsing is done for that label */
  53.     if(!cd || !closed)
  54.         return StateRet_OK;
  55.  
  56.     if(target == CSLLTC_SINGLE)
  57.     {
  58.         LabelOptions_t * lo = CSLabel_getLabelOptions(pCSLabel);
  59.  
  60.         if(lo)
  61.         {
  62.             if(lo->generic.state)
  63.             {
  64.                 cd->rs->generic = TRUE;
  65.             }
  66.  
  67.             if(lo->fur.value && !cd->rs->fur)
  68.             {
  69.                 StrAllocCopy(cd->rs->fur, lo->fur.value);
  70.             }
  71.         }
  72.     }
  73.     else if(target ==  CSLLTC_RATING)
  74.     {
  75.         PICS_RatingsStruct *rating_struct = cd->rs;
  76.         LabelOptions_t * lo = CSLabel_getLabelOptions(pCSLabel);
  77.  
  78.         ratingstr = CSLabel_getRatingStr(pCSLabel);
  79.         ratingname =  CSLabel_getRatingName(pCSLabel);
  80.  
  81.         if(ratingname)
  82.         {
  83.             LabelRating_t * label_rating;
  84.             ServiceInfo_t * service_info;
  85.  
  86.             service_info = CSLabel_getServiceInfo(pCSLabel);
  87.  
  88.             if(service_info && !rating_struct->service)
  89.             {
  90.                rating_struct->service = XP_STRDUP(service_info->rating_service.value); 
  91.             }
  92.  
  93.             label_rating = CSLabel_getLabelRating(pCSLabel);
  94.  
  95.             if(label_rating)
  96.             {
  97.                 double value;
  98.                 PICS_RatingValue *rating_value = XP_NEW_ZAP(PICS_RatingValue);
  99.  
  100.                 value = label_rating->value.value;
  101.                     
  102.                 if(rating_value)
  103.                 {
  104.                     rating_value->value = label_rating->value.value;
  105.                     rating_value->name = XP_STRDUP(label_rating->identifier.value);
  106.  
  107.                     if(rating_value->name)
  108.                     {
  109.                         /* insert it into the list */
  110.                         XP_ListAddObject(rating_struct->ratings, rating_value);
  111.                     }
  112.                     else
  113.                     {
  114.                         /* error, cleanup */
  115.                         XP_FREE(rating_value);
  116.                     }
  117.                 }
  118.             }
  119.         }
  120.  
  121.     }
  122.     return StateRet_OK;
  123. }
  124.  
  125. PRIVATE StateRet_t 
  126. parse_error_handler(CSLabel_t * pCSLabel, CSParse_t * pCSParse,
  127.                              const char * token, char demark,
  128.                              StateRet_t errorCode)
  129. {
  130.     return errorCode;
  131. }
  132.  
  133. /* return NULL or ratings struct */
  134. PUBLIC PICS_RatingsStruct * 
  135. PICS_ParsePICSLable(char * label)
  136. {
  137.     CSParse_t *CSParse_handle;
  138.     ClosureData *cd;
  139.     PICS_RatingsStruct *rs;
  140.     CSDoMore_t status;
  141.  
  142.     if(!label)
  143.         return NULL;
  144.  
  145.     cd = XP_NEW_ZAP(ClosureData);
  146.  
  147.     if(!cd)
  148.         return NULL;
  149.  
  150.     rs = XP_NEW_ZAP(PICS_RatingsStruct);
  151.  
  152.     if(!rs)
  153.     {
  154.         XP_FREE(cd);
  155.         return NULL;
  156.     }
  157.  
  158.     rs->ratings = XP_ListNew();
  159.  
  160.     cd->rs = rs;
  161.  
  162.     /* parse pics label using w3c api */
  163.  
  164.     CSParse_handle = CSParse_newLabel(&target_callback, &parse_error_handler);
  165.  
  166.     if(!CSParse_handle)
  167.         return NULL;
  168.  
  169.     do {
  170.  
  171.         status = CSParse_parseChunk(CSParse_handle, label, XP_STRLEN(label), cd);
  172.  
  173.     } while(status == CSDoMore_more);
  174.  
  175.     if(cd->rs_invalid)
  176.     {
  177.         PICS_FreeRatingsStruct(rs);
  178.         rs = NULL;
  179.     }
  180.  
  181.     XP_FREE(cd);
  182.  
  183.     CSParse_deleteLabel(CSParse_handle);
  184.  
  185.     return(rs);
  186. }
  187.  
  188. PUBLIC void
  189. PICS_FreeRatingsStruct(PICS_RatingsStruct *rs)
  190. {
  191.     if(rs)
  192.     {
  193.         PICS_RatingValue *rv;
  194.         
  195.         while((rv = XP_ListRemoveTopObject(rs->ratings)) != NULL)
  196.         {
  197.             XP_FREE(rv->name);
  198.             XP_FREE(rv);
  199.         }
  200.  
  201.         XP_FREE(rs);
  202.     }
  203. }
  204.  
  205. #define PICS_DOMAIN              "browser.PICS."
  206. #define PICS_ENABLED_PREF         PICS_DOMAIN"ratings_enabled"
  207. #define PICS_MUST_BE_RATED_PREF PICS_DOMAIN"pages_must_be_rated"
  208. #define PICS_DISABLED_FOR_SESSION PICS_DOMAIN"disable_for_this_session"
  209. #define PICS_REENABLE_FOR_SESSION PICS_DOMAIN"reenable_for_this_session"
  210.  
  211. #define JAVA_SECURITY_PASSWORD "signed.applets.capabilitiesDB.password"
  212.  
  213. Bool pics_ratings_enabled = FALSE;
  214. Bool pics_pages_must_be_rated_pref = FALSE;
  215. Bool pics_disabled_for_this_session = FALSE;
  216. int pics_violence_pref = 0;
  217. int pics_sexual_pref = 0;
  218. int pics_language_pref = 0;
  219. int pics_nudity_pref = 0;
  220.  
  221. /* if TRUE the user can allow additional java and JS
  222.  * capibilities.  UniversalFileWrite, etc.
  223.  */
  224. Bool pics_java_capabilities_enabled = TRUE;
  225.  
  226. int PR_CALLBACK
  227. pics_pref_change(const char *pref_name, void *closure)
  228. {
  229.     XP_Bool bool_rv;
  230.  
  231.     if(!PREF_GetBoolPref(PICS_ENABLED_PREF, &bool_rv))
  232.         pics_ratings_enabled = bool_rv;
  233.     if(!PREF_GetBoolPref(PICS_MUST_BE_RATED_PREF, &bool_rv))
  234.         pics_pages_must_be_rated_pref = bool_rv;
  235.     if(!PREF_GetBoolPref(PICS_DISABLED_FOR_SESSION, &bool_rv))
  236.     {
  237.         if(bool_rv)
  238.         {
  239.             pics_disabled_for_this_session = TRUE;
  240.             PREF_SetBoolPref(PICS_DISABLED_FOR_SESSION, FALSE);
  241.         }
  242.     }
  243.     if(!PREF_GetBoolPref(PICS_REENABLE_FOR_SESSION, &bool_rv))
  244.     {
  245.         if(bool_rv)
  246.         {
  247.             pics_disabled_for_this_session = FALSE;
  248.             PREF_SetBoolPref(PICS_REENABLE_FOR_SESSION, FALSE);
  249.         }
  250.     }
  251.  
  252.     return 0;
  253. }
  254.  
  255. PRIVATE char *
  256. pics_hash_password(char *pw)
  257. {
  258.         SECStatus status;
  259.         unsigned char result[SHA1_LENGTH];
  260.  
  261.         status = SHA1_HashBuf(result, (unsigned char *)pw, XP_STRLEN(pw));
  262.  
  263.     if (status != SECSuccess)
  264.         return NULL;
  265.  
  266.     return(BTOA_DataToAscii(result, SHA1_LENGTH));
  267. }
  268.  
  269. PUBLIC void
  270. PICS_Init(MWContext *context)
  271. {
  272.     static XP_Bool first_time=TRUE;
  273.  
  274.     if(!first_time)
  275.     {
  276.         return;
  277.     }
  278.     else
  279.     {
  280.         char *password=NULL;
  281.  
  282.         first_time = FALSE;
  283.  
  284.         /* get the prefs */
  285.         pics_pref_change(PICS_DOMAIN, NULL);
  286.  
  287.         PREF_RegisterCallback(PICS_DOMAIN, pics_pref_change, NULL);
  288.  
  289.         /* check for security pref that password disables the enableing of
  290.          * java permissions
  291.          */
  292.         if(PREF_CopyCharPref(JAVA_SECURITY_PASSWORD, &password))
  293.             password = NULL;
  294.  
  295.         if(password && *password)
  296.         {
  297.             /* get prompt string from registry
  298.              */
  299.             char *prompt_string = XP_GetString(XP_ALERT_PROMPT_JAVA_CAPIBILITIES_PASSWORD);
  300.             char *user_password;
  301.             char *hashed_password;
  302.  
  303. prompt_again:
  304.  
  305.             /* prompt the user for the password
  306.              */
  307.             user_password = FE_PromptPassword(context, prompt_string);
  308.  
  309.             /* ### one-way hash password */
  310.             if(user_password)
  311.             {
  312.                 hashed_password = pics_hash_password(user_password);
  313.             }
  314.             else
  315.             {
  316.                 hashed_password = NULL;
  317.             }
  318.  
  319.             if(!hashed_password)
  320.             {
  321.                 pics_java_capabilities_enabled = FALSE;
  322.             }
  323.             else if(!XP_STRCMP(hashed_password, password))
  324.             {
  325.                 pics_java_capabilities_enabled = TRUE;
  326.             }
  327.             else
  328.             {
  329.                 XP_FREE(user_password);
  330.                 XP_FREE(hashed_password);
  331.                    prompt_string = XP_GetString(XP_ALERT_PROMPT_JAVA_CAPIBILITIES_PASSWORD_FAILED_ONCE);
  332.                 goto prompt_again;
  333.             }
  334.  
  335.             XP_FREEIF(user_password);
  336.             XP_FREEIF(hashed_password);
  337.             
  338.         }
  339.         
  340.         XP_FREEIF(password);
  341.     }
  342. }
  343.  
  344. PUBLIC XP_Bool
  345. PICS_CanUserEnableAdditionalJavaCapabilities(void)
  346. {
  347.     return(pics_java_capabilities_enabled);
  348. }
  349.  
  350. PUBLIC XP_Bool
  351. PICS_IsPICSEnabledByUser(void)
  352. {
  353.     /* short circuit */
  354.     if(pics_disabled_for_this_session)
  355.         return FALSE;
  356.  
  357.     return(pics_ratings_enabled);
  358. }
  359.  
  360. PUBLIC XP_Bool
  361. PICS_AreRatingsRequired(void)
  362. {
  363.     return pics_pages_must_be_rated_pref;
  364. }
  365.  
  366. PRIVATE char *
  367. illegal_to_underscore(char *string)
  368. {
  369.     char* ptr = string;
  370.  
  371.     if(!string)
  372.        return NULL;
  373.  
  374.     if(!XP_IS_ALPHA(*ptr))
  375.            *ptr = '_';
  376.  
  377.     for(ptr++; *ptr; ptr++)
  378.         if(!XP_IS_ALPHA(*ptr) && !XP_IS_DIGIT(*ptr))
  379.            *ptr = '_';
  380.  
  381.     return string;
  382. }
  383.  
  384. PRIVATE char *
  385. lowercase_string(char *string)
  386. {
  387.     char *ptr = string;
  388.  
  389.     if(!string)
  390.         return NULL;
  391.  
  392.     for(; *ptr; ptr++)
  393.         *ptr = XP_TO_LOWER(*ptr);
  394.  
  395.     return string;
  396. }
  397.  
  398. #define PICS_URL_PREFIX "about:pics"
  399.  
  400. /* returns a URL string from a RatingsStruct
  401.  * that includes the service URL and rating info
  402.  */
  403. PUBLIC char *
  404. PICS_RStoURL(PICS_RatingsStruct *rs, char *cur_page_url)
  405. {
  406.     char *rv; 
  407.     char *escaped_cur_page=NULL;
  408.  
  409.     if(cur_page_url)
  410.     {
  411.         escaped_cur_page = NET_Escape(cur_page_url, URL_PATH);    
  412.         if(!escaped_cur_page)
  413.             return NULL;
  414.     }
  415.  
  416.     rv = PR_smprintf("%s?Destination=%s", 
  417.                      PICS_URL_PREFIX, 
  418.                      escaped_cur_page ? escaped_cur_page : "none");
  419.  
  420.     XP_FREE(escaped_cur_page);
  421.  
  422.     if(!rs || !rs->service)
  423.     {
  424.         StrAllocCat(rv, "&NO_RATING");
  425.         return(rv);
  426.     }
  427.     else
  428.     {
  429.         XP_List *list_ptr = rs->ratings;
  430.         PICS_RatingValue *rating_value;
  431.         char *escaped_service = NET_Escape(rs->service, URL_PATH);    
  432.  
  433.         if(!escaped_service)
  434.             return NULL;
  435.  
  436.         StrAllocCat(rv, "&Service=");
  437.         StrAllocCat(rv, escaped_service);
  438.  
  439.         XP_FREE(escaped_service);
  440.  
  441.         while((rating_value = XP_ListNextObject(list_ptr)) != NULL)
  442.         {
  443.  
  444.             char *add;
  445.             char *escaped_name = NET_Escape(
  446.                                      illegal_to_underscore(rating_value->name),
  447.                                      URL_PATH);
  448.  
  449.             if(!escaped_name)
  450.             {
  451.                 XP_FREE(rv); 
  452.                 return NULL;
  453.             }
  454.             
  455.             add = PR_smprintf("&%s=%f", escaped_name, rating_value->value);
  456.  
  457.             XP_FREE(escaped_name);
  458.  
  459.             StrAllocCat(rv, add);
  460.  
  461.             XP_FREE(add);
  462.         }
  463.  
  464.         return rv;
  465.     }
  466.  
  467.     XP_ASSERT(0); /* should never get here */
  468.     return NULL;
  469. }
  470.  
  471. XP_List *pics_tree_ratings=NULL;
  472.  
  473. PRIVATE void
  474. pics_add_rs_to_tree_ratings(PICS_RatingsStruct *rs)
  475. {
  476.     char *path;
  477.  
  478.     if(!pics_tree_ratings)
  479.     {
  480.         pics_tree_ratings = XP_ListNew();
  481.         if(!pics_tree_ratings)
  482.             return;
  483.     }
  484.  
  485.     if(!rs->fur || !rs->generic)
  486.         return;   /* doesn't belong here */
  487.  
  488.     /* make sure it's not in the list already */
  489.     if(PICS_CheckForValidTreeRating(rs->fur))
  490.         return;
  491.  
  492.     /* make sure the fur address smells like a URL and has
  493.      * a real host name (at least two dots) 
  494.      *
  495.      * reject "http://" or "http://www" 
  496.      */
  497.     if(!NET_URL_Type(rs->fur))
  498.         return;
  499.  
  500.     path = NET_ParseURL(rs->fur, GET_PATH_PART);
  501.  
  502.     /* if it has a path it's ok */
  503.     if(!path || !*path)
  504.     {
  505.         /* if it doesn't have a path it needs at least two dots */
  506.         char *ptr;
  507.         char *hostname = NET_ParseURL(rs->fur, GET_HOST_PART);
  508.  
  509.         if(!hostname)
  510.             return;
  511.  
  512.         if(!(ptr = XP_STRCHR(hostname, '.'))
  513.             || !XP_STRCHR(ptr+1, '.'))
  514.         {
  515.             XP_FREE(hostname);
  516.             XP_FREEIF(path);
  517.             return;
  518.         } 
  519.  
  520.         XP_FREE(hostname);
  521.     }
  522.  
  523.     XP_FREE(path);
  524.  
  525.     XP_ListAddObject(pics_tree_ratings, rs->fur);
  526.  
  527.     return;
  528. }
  529.  
  530. PUBLIC XP_Bool
  531. PICS_CheckForValidTreeRating(char *url_address)
  532. {
  533.     XP_List *list_ptr;
  534.     char *valid_tree;
  535.  
  536.     if(!pics_tree_ratings)
  537.         return FALSE;
  538.  
  539.     list_ptr = pics_tree_ratings;
  540.  
  541.     while((valid_tree = XP_ListNextObject(list_ptr)))
  542.     {
  543.         if(!XP_STRNCASECMP(url_address, valid_tree, XP_STRLEN(valid_tree)))
  544.             return TRUE;
  545.     }
  546.  
  547.     return FALSE;
  548. }
  549.  
  550. /* returns TRUE if page should be censored
  551.  * FALSE if page is allowed to be shown
  552.  */
  553. PUBLIC PICS_PassFailReturnVal
  554. PICS_CompareToUserSettings(PICS_RatingsStruct *rs, char *cur_page_url)
  555. {
  556.     int32 int_pref;
  557.     XP_Bool bool_pref;
  558.     char * pref_prefix;
  559.     char * pref_string=NULL;
  560.     char * escaped_service;
  561.     PICS_PassFailReturnVal rv = PICS_RATINGS_PASSED;
  562.     XP_List *list_ptr;
  563.     PICS_RatingValue *rating_value;
  564.  
  565.     if(!rs || !rs->service)
  566.     {
  567.         return PICS_NO_RATINGS;
  568.     }
  569.  
  570. #define PICS_SERVICE_DOMAIN   PICS_DOMAIN"service."
  571. #define PICS_SERVICE_ENABLED  "service_enabled"
  572.  
  573.     /* cycle through list of ratings and compare to the users prefs */
  574.     list_ptr = rs->ratings;
  575.     pref_prefix = XP_STRDUP(PICS_SERVICE_DOMAIN);
  576.  
  577.     /* need to deal with bad characters */
  578.     escaped_service = XP_STRDUP(rs->service);
  579.     escaped_service = illegal_to_underscore(escaped_service);
  580.     escaped_service = lowercase_string(escaped_service);
  581.  
  582.     if(!escaped_service)
  583.         return PICS_RATINGS_FAILED;
  584.  
  585.     StrAllocCat(pref_prefix, escaped_service);
  586.  
  587.     XP_FREE(escaped_service);
  588.  
  589.     if(!pref_prefix)
  590.         return PICS_RATINGS_FAILED;
  591.  
  592.     /* verify that this type of rating system is enabled */
  593.     pref_string = PR_smprintf("%s.%s", pref_prefix, PICS_SERVICE_ENABLED);
  594.     
  595.     if(!pref_string)
  596.         goto cleanup;
  597.  
  598.     if(!PREF_GetBoolPref(pref_string, &bool_pref))
  599.     {
  600.         if(!bool_pref)
  601.         {
  602.             /* this is an unenabled ratings service */
  603.             rv = PICS_NO_RATINGS;
  604.             XP_FREE(pref_string);
  605.             goto cleanup;
  606.         }
  607.     }
  608.     else
  609.     {
  610.         /* this is an unsupported ratings service */
  611.         rv = PICS_NO_RATINGS;
  612.         XP_FREE(pref_string);
  613.         goto cleanup;
  614.     }
  615.  
  616.     XP_FREE(pref_string);
  617.  
  618.     while((rating_value = XP_ListNextObject(list_ptr)) != NULL)
  619.     {
  620.         /* compose pref lookup string */
  621.         pref_string = PR_smprintf("%s.%s", 
  622.                                 pref_prefix, 
  623.                                 illegal_to_underscore(rating_value->name));
  624.  
  625.         if(!pref_string)
  626.             goto cleanup;
  627.  
  628.         /* find the value in the prefs if it exists
  629.          * if it does compare it to the value given and if
  630.          * less than, censer the page.
  631.          */
  632.         if(!PREF_GetIntPref(pref_string, &int_pref))
  633.         {
  634.             if(rating_value->value > int_pref)
  635.             {
  636.                 rv = PICS_RATINGS_FAILED;
  637.                 XP_FREE(pref_string);
  638.                 goto cleanup;
  639.             }
  640.         }
  641.  
  642.         XP_FREE(pref_string);
  643.     }
  644.  
  645. cleanup:
  646.  
  647.     XP_FREE(pref_prefix);
  648.  
  649.     /* make sure this rating applies to this page */
  650.     if(rs->fur)
  651.     {
  652.         if(XP_STRNCASECMP(cur_page_url, rs->fur, XP_STRLEN(rs->fur)))
  653.             rv = PICS_NO_RATINGS;
  654.     }
  655.  
  656.     if(rv == PICS_RATINGS_PASSED && rs->generic)
  657.     {
  658.         /* rating should apply to a whole tree, add to list */
  659.         pics_add_rs_to_tree_ratings(rs);        
  660.     }
  661.  
  662.     return rv;
  663. }
  664.  
  665.