home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / LYMap.c < prev    next >
C/C++ Source or Header  |  1998-03-25  |  16KB  |  591 lines

  1. /*            Lynx Client-side Image MAP Support           LYMap.c
  2. **            ==================================
  3. **
  4. **    Author: FM    Foteos Macrides (macrides@sci.wfbr.edu)
  5. **
  6. */
  7.  
  8. #include <HTUtils.h>
  9. #include <tcp.h>
  10. #include <HTTP.h>
  11. #include <HTAnchor.h>
  12. #include <HTAccess.h>
  13. #include <HTFormat.h>
  14. #include <HTParse.h>
  15. #include <HTAlert.h>
  16. #include <LYUtils.h>
  17. #include <LYMap.h>
  18. #include <GridText.h>
  19. #include <LYSignal.h>
  20. #include <LYGlobalDefs.h>
  21. #include <LYKeymap.h>
  22. #include <LYCharUtils.h>
  23.  
  24. #ifdef DIRED_SUPPORT
  25. #include <LYUpload.h>
  26. #include <LYLocal.h>
  27. #endif
  28.  
  29. #include <LYexit.h>
  30. #include <LYLeaks.h>
  31.  
  32. #define FREE(x) if (x) {free(x); x=NULL;}
  33.  
  34. typedef struct _LYMapElement {
  35.    char * address;
  36.    char * title;
  37. #ifndef DONT_TRACK_INTERNAL_LINKS
  38.    BOOL   intern_flag;
  39. #endif
  40. } LYMapElement;
  41.  
  42. typedef struct _LYImageMap {
  43.    char * address;
  44.    char * title;
  45.    HTList * elements;
  46. } LYImageMap;
  47.  
  48. struct _HTStream
  49. {
  50.   HTStreamClass * isa;
  51. };
  52.  
  53. PRIVATE HTList * LynxMaps = NULL;
  54.  
  55. PUBLIC BOOL LYMapsOnly = FALSE;
  56.  
  57. /*
  58.  *  Utility for freeing a list of MAPs.
  59.  */
  60. PUBLIC void ImageMapList_free ARGS1(
  61.     HTList *,        theList)
  62. {
  63.     LYImageMap *map;
  64.     LYMapElement *element;
  65.     HTList *cur = theList;
  66.     HTList *current;
  67.  
  68.     if (!cur)
  69.     return;
  70.  
  71.     while (NULL != (map = (LYImageMap *)HTList_nextObject(cur))) {
  72.     FREE(map->address);
  73.     FREE(map->title);
  74.     if (map->elements) {
  75.         current = map->elements;
  76.         while (NULL !=
  77.            (element = (LYMapElement *)HTList_nextObject(current))) {
  78.         FREE(element->address);
  79.         FREE(element->title);
  80.         FREE(element);
  81.         }
  82.         HTList_delete(map->elements);
  83.         map->elements = NULL;
  84.     }
  85.     FREE(map);
  86.     }
  87.     HTList_delete(theList);
  88.     return;
  89. }
  90.  
  91. /*
  92.  *  Utility for freeing the global list of MAPs. - kw
  93.  */
  94. PRIVATE void LYLynxMaps_free NOARGS
  95. {
  96.     ImageMapList_free(LynxMaps);
  97.     LynxMaps = NULL;
  98.     return;
  99. }
  100.  
  101. /*
  102.  *  We keep two kinds of lists:
  103.  *  - A global list (LynxMaps) shared by MAPs from all documents that
  104.  *    do not have POST data.
  105.  *  - For each response to a POST which contains MAPs, a list specific
  106.  *    to this combination of URL and post_data.  It is kept in the
  107.  *    HTParentAnchor structure and is freed when the document is removed
  108.  *    from memory, in the course of normal removal of anchors.
  109.  *    MAPs from POST responses can only be accessed via internal links,
  110.  *    i.e. from within the same document (with the same post_data).
  111.  *    The notion of "same document" is extended, so that LYNXIMGMAP:
  112.  *    and List Page screens are logically part of the document on which
  113.  *    they are based. - kw
  114.  *
  115.  *  If DONT_TRACK_INTERNAL_LINKS is defined, only the global list will
  116.  *  be used for all MAPs.
  117.  *
  118.  */
  119.  
  120. /*
  121.  *  Utility for creating an LYImageMap list, if it doesn't
  122.  *  exist already, adding LYImageMap entry structures if needed, and
  123.  *  removing any LYMapElements in a pre-existing LYImageMap entry so that
  124.  *  it will have only those from AREA tags for the current analysis of
  125.  *  MAP element content. - FM
  126.  */
  127. PUBLIC BOOL LYAddImageMap ARGS3(
  128.     char *,     address,
  129.     char *,     title,
  130.     HTParentAnchor *, node_anchor)
  131. {
  132.     LYImageMap *new = NULL;
  133.     LYImageMap *old = NULL;
  134.     HTList *cur = NULL;
  135.     HTList *theList = NULL;
  136.     HTList *curele = NULL;
  137.     LYMapElement *ele = NULL;
  138.  
  139.     if (!(address && *address))
  140.     return FALSE;
  141.     if (!(node_anchor && node_anchor->address))
  142.     return FALSE;
  143.  
  144.     /*
  145.      *    Set theList to either the global LynxMaps list or, if we
  146.      *    are associated with post data, the specific list.  The
  147.      *    list is created if it doesn't already exist. - kw
  148.      */
  149. #ifndef DONT_TRACK_INTERNAL_LINKS
  150.     if (node_anchor->post_data) {
  151.     /*
  152.      *  We are handling a MAP element found while parsing
  153.      *  node_anchor's stream of data, and node_anchor has
  154.      *  post_data associated and should therefore represent
  155.      *  a POST response, so use the specific list. - kw
  156.      */
  157.     theList = node_anchor->imaps;
  158.     if (!theList) {
  159.         theList = node_anchor->imaps = HTList_new();
  160.     }
  161.     } else
  162. #endif
  163.     {
  164.     if (!LynxMaps) {
  165.         LynxMaps = HTList_new();
  166.         atexit(LYLynxMaps_free);
  167.     }
  168.     theList = LynxMaps;
  169.     }
  170.  
  171.     if (theList) {
  172.     cur = theList;
  173.     while (NULL != (old = (LYImageMap *)HTList_nextObject(cur))) {
  174.         if (!strcmp(old->address, address)) {
  175.         FREE(old->address);
  176.         FREE(old->title);
  177.         if (old->elements) {
  178.             curele = old->elements;
  179.             while (NULL !=
  180.                (ele = (LYMapElement *)HTList_nextObject(curele))) {
  181.             FREE(ele->address);
  182.             FREE(ele->title);
  183.             FREE(ele);
  184.             }
  185.             HTList_delete(old->elements);
  186.             old->elements = NULL;
  187.         }
  188.         break;
  189.         }
  190.     }
  191.     }
  192.  
  193.     new = (old != NULL) ?
  194.             old : (LYImageMap *)calloc(1, sizeof(LYImageMap));
  195.     if (new == NULL) {
  196.     perror("Out of memory in LYAddImageMap");
  197.     return FALSE;
  198.     }
  199.     StrAllocCopy(new->address, address);
  200.     if (title && *title)
  201.     StrAllocCopy(new->title, title);
  202.     if (new != old)
  203.     HTList_addObject(theList, new);
  204.     return TRUE;
  205. }
  206.  
  207. /*
  208.  * Utility for adding LYMapElements to LYImageMaps
  209.  * in the appropriate list. - FM
  210.  */
  211. PUBLIC BOOL LYAddMapElement ARGS5(
  212.     char *,     map,
  213.     char *,     address,
  214.     char *,     title,
  215.     HTParentAnchor *, node_anchor,
  216.     BOOL,        intern_flag)
  217. {
  218.     LYMapElement *new = NULL;
  219.     LYImageMap *theMap = NULL;
  220.     HTList *theList = NULL;
  221.     HTList *cur = NULL;
  222.  
  223.     if (!(map && *map && address && *address))
  224.     return FALSE;
  225.     if (!(node_anchor && node_anchor->address))
  226.     return FALSE;
  227.  
  228.     /*
  229.      *    Set theList to either the global LynxMaps list or, if we
  230.      *    are associated with post data, the specific list.  The
  231.      *    list should already exist, since this function is only called
  232.      *    if the AREA tag we are handling was within a MAP element
  233.      *    in node_anchor's stream of data, so that LYAddImageMap has
  234.      *    been called. - kw
  235.      */
  236. #ifndef DONT_TRACK_INTERNAL_LINKS
  237.     if (node_anchor->post_data) {
  238.     /*
  239.      *  We are handling an AREA tag found while parsing
  240.      *  node_anchor's stream of data, and node_anchor has
  241.      *  post_data associated and should therefore represent
  242.      *  a POST response, so use the specific list. - kw
  243.      */
  244.     theList = node_anchor->imaps;
  245.     if (!theList)
  246.         return FALSE;
  247.     } else
  248. #endif
  249.     {
  250.     if (!LynxMaps)
  251.         LYAddImageMap(map, NULL, node_anchor);
  252.     theList = LynxMaps;
  253.     }
  254.  
  255.     cur = theList;
  256.     while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
  257.     if (!strcmp(theMap->address, map)) {
  258.         break;
  259.     }
  260.     }
  261.     if (!theMap)
  262.     return FALSE;
  263.     if (!theMap->elements)
  264.     theMap->elements = HTList_new();
  265.     cur = theMap->elements;
  266.     while (NULL != (new = (LYMapElement *)HTList_nextObject(cur))) {
  267.     if (!strcmp(new->address, address)) {
  268.         FREE(new->address);
  269.         FREE(new->title);
  270.         HTList_removeObject(theMap->elements, new);
  271.         FREE(new);
  272.         break;
  273.     }
  274.     }
  275.  
  276.     new = (LYMapElement *)calloc(1, sizeof(LYMapElement));
  277.     if (new == NULL) {
  278.     perror("Out of memory in LYAddMapElement");
  279.     return FALSE;
  280.     }
  281.     StrAllocCopy(new->address, address);
  282.     if (title && *title)
  283.     StrAllocCopy(new->title, title);
  284.     else
  285.     StrAllocCopy(new->title, address);
  286. #ifndef DONT_TRACK_INTERNAL_LINKS
  287.     new->intern_flag = intern_flag;
  288. #endif
  289.     HTList_appendObject(theMap->elements, new);
  290.     return TRUE;
  291. }
  292.  
  293. /*
  294.  *  Utility for checking whether an LYImageMap entry
  295.  *  with a given address already exists in the LynxMaps
  296.  *  structure. - FM
  297.  */
  298. PUBLIC BOOL LYHaveImageMap ARGS1(
  299.     char *,     address)
  300. {
  301.     LYImageMap *Map;
  302.     HTList *cur = LynxMaps;
  303.  
  304.     if (!(cur && address && *address != '\0'))
  305.     return FALSE;
  306.  
  307.     while (NULL != (Map = (LYImageMap *)HTList_nextObject(cur))) {
  308.     if (!strcmp(Map->address, address)) {
  309.         return TRUE;
  310.     }
  311.     }
  312.  
  313.     return FALSE;
  314. }
  315.  
  316. /*
  317.  *  Fills in a DocAddress structure for getting the HTParentAnchor of
  318.  *  the underlying resource.  ALso returns a pointer to that anchor in
  319.  *  *punderlying if we are dealing with POST data. - kw
  320.  *
  321.  *  address  is the address of the underlying resource, i.e. the one
  322.  *         containing the MAP element, the MAP's name appended as
  323.  *         fragment is ignored.
  324.  *  anAnchor is the LYNXIMGMAP: anchor; if it is associated with POST
  325.  *         data, we want the specific list, otherwise the global list.
  326.  */
  327. PRIVATE void fill_DocAddress ARGS4(
  328.     DocAddress *,    wwwdoc,
  329.     char *,        address,
  330.     HTParentAnchor *,    anAnchor,
  331.     HTParentAnchor **,    punderlying)
  332. {
  333.     HTParentAnchor * underlying;
  334.     if (anAnchor && anAnchor->post_data) {
  335.     wwwdoc->address = address;
  336.     wwwdoc->post_data = anAnchor->post_data;
  337.     wwwdoc->post_content_type = anAnchor->post_content_type;
  338.     wwwdoc->bookmark = NULL;
  339.     wwwdoc->isHEAD = FALSE;
  340.     wwwdoc->safe = FALSE;
  341.     underlying = HTAnchor_parent(HTAnchor_findAddress(wwwdoc));
  342.     if (underlying->safe)
  343.         wwwdoc->safe = TRUE;
  344.     if (punderlying)
  345.         *punderlying = underlying;
  346.     } else {
  347.     wwwdoc->address = address;
  348.     wwwdoc->post_data = NULL;
  349.     wwwdoc->post_content_type = NULL;
  350.     wwwdoc->bookmark = NULL;
  351.     wwwdoc->isHEAD = FALSE;
  352.     wwwdoc->safe = FALSE;
  353.     if (punderlying)
  354.         *punderlying = NULL;
  355.     }
  356. }
  357.  
  358. /*
  359.  *  Get the appropriate list for creating a LYNXIMGMAP: pseudo-
  360.  *  document: either the global list (LynxMaps), or the specific
  361.  *  list if a List Page for a POST response is requested.  Also
  362.  *  fill in the DocAddress structure etc. by calling fill_DocAddress().
  363.  *
  364.  *  address is the address of the underlying resource, i.e. the one
  365.  *        containing the MAP element, the MAP's name appended as
  366.  *        fragment is ignored.
  367.  *  anchor  is the LYNXIMGMAP: anchor for which LYLoadIMGmap() is
  368.  *        requested; if it is associated with POST data, we want the
  369.  *        specific list for this combination of address+post_data.
  370.  *
  371.  * if DONT_TRACK_INTERNAL_LINKS is defined, the Anchor passed to
  372.  * LYLoadIMGmap() will never have post_data, so that the global list
  373.  * will be used. - kw
  374.  */
  375. PRIVATE HTList * get_the_list ARGS4(
  376.     DocAddress *,    wwwdoc,
  377.     char *,        address,
  378.     HTParentAnchor *,    anchor,
  379.     HTParentAnchor **,    punderlying)
  380. {
  381.     if (anchor && anchor->post_data) {
  382.     fill_DocAddress(wwwdoc, address, anchor, punderlying);
  383.     if (punderlying && *punderlying)
  384.         return (*punderlying)->imaps;
  385.     return anchor->imaps;
  386.     } else {
  387.     fill_DocAddress(wwwdoc, address, NULL, punderlying);
  388.     return LynxMaps;
  389.     }
  390. }
  391.  
  392. /*    LYLoadIMGmap - F.Macrides (macrides@sci.wfeb.edu)
  393. **    ------------
  394. **    Create a text/html stream with a list of links
  395. **    for HyperText References in AREAs of a MAP.
  396. */
  397.  
  398. PRIVATE int LYLoadIMGmap ARGS4 (
  399.     CONST char *,        arg,
  400.     HTParentAnchor *,    anAnchor,
  401.     HTFormat,        format_out,
  402.     HTStream*,        sink)
  403. {
  404.     HTFormat format_in = WWW_HTML;
  405.     HTStream *target = NULL;
  406.     char buf[1024];
  407.     LYMapElement *new = NULL;
  408.     LYImageMap *theMap = NULL;
  409.     char *MapTitle = NULL;
  410.     char *MapAddress = NULL;
  411.     HTList *theList;
  412.     HTList *cur = NULL;
  413.     char *address = NULL;
  414.     char *cp = NULL;
  415.     DocAddress WWWDoc;
  416.     HTParentAnchor * underlying;
  417.     BOOL old_cache_setting = LYforce_no_cache;
  418.     BOOL old_reloading = reloading;
  419.     HTFormat old_format_out = HTOutputFormat;
  420.  
  421.     if (!strncasecomp(arg, "LYNXIMGMAP:", 11)) {
  422.     address = (char * )(arg + 11);
  423.     }
  424.     if (!(address && strchr(address, ':'))) {
  425.     HTAlert(MISDIRECTED_MAP_REQUEST);
  426.     return(HT_NOT_LOADED);
  427.     }
  428.  
  429.     theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
  430.     if (WWWDoc.safe)
  431.     anAnchor->safe = TRUE;
  432.  
  433.     if (!theList) {
  434.     if (anAnchor->post_data && !WWWDoc.safe &&
  435.         ((underlying && underlying->document && !LYforce_no_cache) ||
  436.          HTConfirm(
  437. #if __STDC__
  438.         "LYNXIMGMAP: "
  439. #endif
  440.         CONFIRM_POST_RESUBMISSION) != TRUE)) {
  441.         HTAlert("Image map from POST response not available!");
  442.         return(HT_NOT_LOADED);
  443.     }
  444.     LYforce_no_cache = TRUE;
  445.     reloading = TRUE;
  446.     HTOutputFormat = WWW_PRESENT;
  447.     LYMapsOnly = TRUE;
  448.     if (!HTLoadAbsolute(&WWWDoc)) {
  449.         LYforce_no_cache = old_cache_setting;
  450.         reloading = old_reloading;
  451.         HTOutputFormat = old_format_out;
  452.         LYMapsOnly = FALSE;
  453.         HTAlert(MAP_NOT_ACCESSIBLE);
  454.         return(HT_NOT_LOADED);
  455.     }
  456.     LYforce_no_cache = old_cache_setting;
  457.     reloading = old_reloading;
  458.     HTOutputFormat = old_format_out;
  459.     LYMapsOnly = FALSE;
  460.     theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
  461.     }
  462.  
  463.     if (!theList) {
  464.     HTAlert(MAPS_NOT_AVAILABLE);
  465.     return(HT_NOT_LOADED);
  466.     }
  467.  
  468.     cur = theList;
  469.     while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
  470.     if (!strcmp(theMap->address, address)) {
  471.         break;
  472.     }
  473.     }
  474.     if (!(theMap && theMap->elements)) {
  475.     if (anAnchor->post_data && !WWWDoc.safe &&
  476.         ((underlying && underlying->document && !LYforce_no_cache) ||
  477.         HTConfirm(
  478. #if __STDC__
  479.         "LYNXIMGMAP: "
  480. #endif
  481.         CONFIRM_POST_RESUBMISSION) != TRUE)) {
  482.         HTAlert("Image map from POST response not available!");
  483.         return(HT_NOT_LOADED);
  484.     }
  485.     LYforce_no_cache = TRUE;
  486.     reloading = TRUE;
  487.     HTOutputFormat = WWW_PRESENT;
  488.     LYMapsOnly = TRUE;
  489.     if (!HTLoadAbsolute(&WWWDoc)) {
  490.         LYforce_no_cache = old_cache_setting;
  491.         reloading = old_reloading;
  492.         HTOutputFormat = old_format_out;
  493.         LYMapsOnly = FALSE;
  494.         HTAlert(MAP_NOT_ACCESSIBLE);
  495.         return(HT_NOT_LOADED);
  496.     }
  497.     LYforce_no_cache = old_cache_setting;
  498.     reloading = old_reloading;
  499.     HTOutputFormat = old_format_out;
  500.     LYMapsOnly = FALSE;
  501.     cur = get_the_list(&WWWDoc, address, anAnchor, &underlying);
  502.     while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
  503.         if (!strcmp(theMap->address, address)) {
  504.         break;
  505.         }
  506.     }
  507.     if (!(theMap && theMap->elements)) {
  508.         HTAlert(MAP_NOT_AVAILABLE);
  509.         return(HT_NOT_LOADED);
  510.     }
  511.     }
  512.  
  513. #ifdef DONT_TRACK_INTERNAL_LINKS
  514.     anAnchor->no_cache = TRUE;
  515. #endif
  516.  
  517.     target = HTStreamStack(format_in,
  518.                format_out,
  519.                sink, anAnchor);
  520.  
  521.     if (!target || target == NULL) {
  522.     sprintf(buf, CANNOT_CONVERT_I_TO_O,
  523.         HTAtom_name(format_in), HTAtom_name(format_out));
  524.     HTAlert(buf);
  525.     return(HT_NOT_LOADED);
  526.     }
  527.  
  528.     if (theMap->title && *theMap->title) {
  529.     StrAllocCopy(MapTitle, theMap->title);
  530.     } else if (anAnchor->title && *anAnchor->title) {
  531.     StrAllocCopy(MapTitle, anAnchor->title);
  532.     } else if (LYRequestTitle && *LYRequestTitle &&
  533.            strcasecomp(LYRequestTitle, "[USEMAP]")) {
  534.     StrAllocCopy(MapTitle, LYRequestTitle);
  535.     } else if ((cp=strrchr(address, '#')) != NULL) {
  536.     StrAllocCopy(MapTitle, (cp+1));
  537.     }
  538.     if (!(MapTitle && *MapTitle)) {
  539.     StrAllocCopy(MapTitle, "[USEMAP]");
  540.     } else {
  541.     LYEntify(&MapTitle, TRUE);
  542.     }
  543.  
  544.     sprintf(buf,"<head>\n<title>%s</title>\n</head>\n<body>\n", MapTitle);
  545.     (*target->isa->put_block)(target, buf, strlen(buf));
  546.  
  547.     sprintf(buf,"<h1><em>%s</em></h1>\n", MapTitle);
  548.     (*target->isa->put_block)(target, buf, strlen(buf));
  549.  
  550.     StrAllocCopy(MapAddress, address);
  551.     LYEntify(&MapAddress, FALSE);
  552.     sprintf(buf,"<h2><em>MAP:</em> %s</h2>\n", MapAddress);
  553.     (*target->isa->put_block)(target, buf, strlen(buf));
  554.  
  555.     sprintf(buf, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
  556.                     "ol" : "ul"));
  557.     (*target->isa->put_block)(target, buf, strlen(buf));
  558.     cur = theMap->elements;
  559.     while (NULL != (new=(LYMapElement *)HTList_nextObject(cur))) {
  560.     StrAllocCopy(MapAddress, new->address);
  561.     LYEntify(&MapAddress, FALSE);
  562.     (*target->isa->put_block)(target, "<li><a href=\"", 13);
  563.     (*target->isa->put_block)(target, MapAddress, strlen(MapAddress));
  564. #ifndef DONT_TRACK_INTERNAL_LINKS
  565.     if (new->intern_flag)
  566.         (*target->isa->put_block)(target, "\" TYPE=\"internal link\"\n>",24);
  567.     else
  568. #endif
  569.         (*target->isa->put_block)(target, "\"\n>", 3);
  570.     StrAllocCopy(MapTitle, new->title);
  571.     LYEntify(&MapTitle, TRUE);
  572.     (*target->isa->put_block)(target, MapTitle, strlen(MapTitle));
  573.     (*target->isa->put_block)(target, "</a>\n", 5);
  574.     }
  575.     sprintf(buf,"</%s>\n</body>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
  576.                      "ol" : "ul"));
  577.     (*target->isa->put_block)(target, buf, strlen(buf));
  578.  
  579.     (*target->isa->_free)(target);
  580.     FREE(MapAddress);
  581.     FREE(MapTitle);
  582.     return(HT_LOADED);
  583. }
  584.  
  585. #ifdef GLOBALDEF_IS_MACRO
  586. #define _LYIMGMAP_C_GLOBALDEF_1_INIT { "LYNXIMGMAP", LYLoadIMGmap, 0}
  587. GLOBALDEF (HTProtocol,LYLynxIMGmap,_LYIMGMAP_C_GLOBALDEF_1_INIT);
  588. #else
  589. GLOBALDEF PUBLIC HTProtocol LYLynxIMGmap = {"LYNXIMGMAP", LYLoadIMGmap, 0};
  590. #endif /* GLOBALDEF_IS_MACRO */
  591.