home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / rdf / src / rdfparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.8 KB  |  432 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. /* 
  20.    This file implements parsing support for the rdf data model.
  21.    For more information on this file, contact rjc or guha 
  22.    For more information on RDF, look at the RDF section of www.mozilla.org
  23. */
  24.  
  25. #include "rdfparse.h"
  26. #include "mcf.h"
  27. #include "mcff2mcf.h"
  28.  
  29.  
  30.  
  31. char *
  32. getHref(char** attlist)
  33. {
  34.     char* ans = getAttributeValue(attlist, "rdf:href");
  35.     if (ans != NULL) {
  36.             return ans;
  37.     } else return getAttributeValue(attlist, "href");
  38. }
  39.  
  40.  
  41.  
  42. int
  43. parseNextRDFXMLBlob (NET_StreamClass *stream, char* blob, int32 size)
  44. {
  45.   RDFFile f;
  46.   int32 n, last, m;
  47.   PRBool somethingseenp = 0;
  48.   n = last = 0;
  49.  
  50.   f = (RDFFile)stream->data_object;
  51.   if ((f == NULL) || (size < 0)) {
  52.     return MK_INTERRUPTED;
  53.   }
  54.  
  55.   while (n < size) {
  56.     char c = blob[n];
  57.     m = 0;
  58.     somethingseenp = 0;
  59.     memset(f->line, '\0', RDF_BUF_SIZE);
  60.     if (f->holdOver[0] != '\0') {
  61.       memcpy(f->line, f->holdOver, strlen(f->holdOver));
  62.       m = strlen(f->holdOver);
  63.       somethingseenp = 1;
  64.       memset(f->holdOver, '\0', RDF_BUF_SIZE);
  65.     }   
  66.     while ((n < size) && (wsc(c))) {c = blob[++n];}
  67.   /*  f->line[m++] = c;
  68.     c = blob[++n]; */
  69.     while ((m < RDF_BUF_SIZE) && (c != '<') && (c != '>')) {
  70.       f->line[m] = c;
  71.       m++;
  72.       somethingseenp = (somethingseenp || (!(wsc(c))));
  73.       n++;    
  74.       if (n < size) c = blob[n]; 
  75.       else break;
  76.     }
  77.     if (c == '>') f->line[m] = c;
  78.     n++;
  79.     if (m > 0) {
  80.       if ((c == '<') || (c == '>')) {
  81.     last = n;
  82.     if (c == '<') f->holdOver[0] = '<'; 
  83.     if (somethingseenp == 1) parseNextRDFToken(f, f->line);
  84.       } else if (size > last) {
  85.     memcpy(f->holdOver, f->line, m);
  86.       }
  87.     } else if (c == '<') f->holdOver[0] = '<';
  88.   }
  89.   return(size);
  90. }
  91.  
  92.  
  93.  
  94. void
  95. parseRDFProcessingInstruction (RDFFile f, char* token)
  96. {
  97.   char* attlist[2*MAX_ATTRIBUTES+1];
  98.   char* elementName;  
  99.   tokenizeElement(token, attlist, &elementName);
  100.   if (strcmp(elementName, "xml:namespace") == 0) {
  101.     char* as = getAttributeValue(attlist, "as");
  102.     char* url = getHref(attlist);
  103.     if ((as != NULL) && (url != NULL)) {
  104.       XMLNameSpace ns = (XMLNameSpace)getMem(sizeof(struct XMLNameSpaceStruct));
  105.       ns->as = as;
  106.       ns->url = url;
  107.       ns->next = f->namespaces;
  108.       f->namespaces = ns;
  109.     }
  110.   }  
  111.  
  112.  
  113.  
  114. void
  115. freeNamespaces (RDFFile f)
  116. {
  117.   XMLNameSpace ns1 = f->namespaces;
  118.   while (ns1) {
  119.     XMLNameSpace next = ns1->next;
  120.     freeMem(ns1->as);
  121.     freeMem(ns1->url);
  122.     freeMem(ns1);
  123.     ns1 = next;
  124.   }
  125. }
  126.  
  127.  
  128.  
  129. PR_PUBLIC_API(char *)
  130. getAttributeValue (char** attlist, char* elName)
  131. {
  132.   size_t n = 0;
  133.   if (!attlist) return NULL;
  134.   while ((n < 2*MAX_ATTRIBUTES) && (*(attlist + n) != NULL)) {
  135.     if (strcmp(*(attlist + n), elName) == 0) return *(attlist + n + 1);
  136.     n = n + 2;
  137.   }
  138.   return NULL;
  139. }
  140.  
  141.  
  142.  
  143. PRBool
  144. tagEquals (RDFFile f, char* tag1, char* tag2)
  145. {
  146.     return (strcmp(tag1, tag2) == 0);
  147. }
  148.  
  149.  
  150.  
  151. void
  152. addElementProps (char** attlist, char* elementName, RDFFile f, RDF_Resource obj)
  153. {
  154.   uint32 count = 0;
  155.   while (count < 2*MAX_ATTRIBUTES) {
  156.     char* attName = attlist[count++];
  157.     char* attValue = attlist[count++];
  158.     if ((attName == NULL) || (attValue == NULL)) break;
  159.     if (!tagEquals(f, attName, "href") && !tagEquals(f, attName, "rdf:href") 
  160.         && !tagEquals(f, attName, "id")) {
  161.       addSlotValue(f, obj, RDF_GetResource(NULL, attName, true), copyString(attValue), 
  162.            RDF_STRING_TYPE, 1);
  163.     }
  164.   }
  165. }
  166.  
  167.  
  168.  
  169. PRBool
  170. knownObjectElement (char* eln)
  171. {
  172.     return (strcmp(eln, "RDF:Description") == 0);
  173. }
  174.  
  175.  
  176.  
  177. char *
  178. possiblyMakeAbsolute (RDFFile f, char* url)
  179. {
  180.     if (strchr(url, ':') != NULL) {
  181.     return copyString(url);
  182.   } else {
  183.     char* ans = getMem(strlen(f->url) + strlen(url)+2);
  184.     sprintf(ans, "%s#%s", f->url, url);
  185.     return ans;
  186.   }
  187. }
  188.  
  189.  
  190.  
  191. PRBool
  192. containerTagp (RDFFile f, char* elementName)
  193. {
  194.  return (tagEquals(f, elementName, "Container") || 
  195.         tagEquals(f, elementName, "Topic") ||
  196.         (tagEquals(f, elementName, "RelatedLinks")));
  197. }
  198.  
  199.  
  200.  
  201. RDF_Resource
  202. ResourceFromElementName (RDFFile f, char* elementName)
  203. {
  204.   if ((strchr(elementName, ':') == NULL) ) {
  205.     return RDF_GetResource(NULL, elementName, 1);
  206.   } else {
  207.     XMLNameSpace ns = f->namespaces;
  208.     while (ns) {
  209.       if (startsWith(ns->as, elementName)) {
  210.         RDF_Resource ans;
  211.         size_t asn =  strlen(ns->as);
  212.         size_t urln = strlen(ns->url);
  213.         char* url = getMem(strlen(ns->url) + strlen(elementName)-asn);
  214.         memcpy(url, ns->url, urln);
  215.         strcat(url, &elementName[asn+1]);
  216.         ans = RDF_GetResource(NULL, url, 1);
  217.         freeMem(url);
  218.         return ans;
  219.       }
  220.       ns = ns->next;
  221.     }
  222.     return RDF_GetResource(NULL, elementName, 1);
  223.   }
  224. }
  225.         
  226.  
  227.  
  228. void
  229. parseNextRDFToken (RDFFile f, char* token)
  230. {
  231.   if (token[0] != '<')   {
  232.     if ((f->status == EXPECTING_OBJECT) && (f->depth > 1)) {
  233.       RDF_Resource u = f->stack[f->depth-2];
  234.       RDF_Resource s = f->stack[f->depth-1];
  235.       addSlotValue(f, u, s, copyString(token), RDF_STRING_TYPE, 1);
  236.     } 
  237.   } else if  (startsWith("<!--", token)) {
  238.     return;
  239.   } else if (token[1] == '?')  {
  240.     parseRDFProcessingInstruction(f, token);
  241.   } else if (token[1] == '/') {
  242.     if ((f->status != EXPECTING_OBJECT) && (f->status != EXPECTING_PROPERTY)) return;
  243.     if (f->depth > 0) f->depth--;
  244.     f->status = (f->status == EXPECTING_OBJECT ? EXPECTING_PROPERTY : EXPECTING_OBJECT);
  245.   } else if ((f->status == 0) && startsWith("<RDF:RDF>", token)) {
  246.       f->status = EXPECTING_OBJECT;
  247.   } else if (startsWith("<RelatedLinks", token)) {
  248.     f->stack[f->depth++] = f->top;
  249.     f->status = EXPECTING_PROPERTY;
  250.   } else {
  251.     PRBool emptyElementp = (token[strlen(token)-2] == '/');
  252.     char* attlist[2*MAX_ATTRIBUTES+1];
  253.     char* elementName;
  254.     if ((f->status != EXPECTING_OBJECT) && (f->status != EXPECTING_PROPERTY)) return;
  255.     tokenizeElement(token, attlist, &elementName);
  256.     if ((f->status == EXPECTING_PROPERTY) && (knownObjectElement(elementName))) return;
  257.     if (f->status == EXPECTING_OBJECT) {
  258.       char* url = NULL;
  259.       RDF_Resource obj;
  260.       uint16 count = 0;      
  261.       url = getHref(attlist);
  262.       if (url == NULL) url = getAttributeValue(attlist, "id"); 
  263.       if (url) url = possiblyMakeAbsolute(f, url);
  264.       obj =  RDF_GetResource(NULL, url, true);
  265.       if (url) freeMem(url);
  266.       addToResourceList(f, obj);
  267.       addElementProps (attlist, elementName, f, obj) ;
  268.       if (!tagEquals(f, elementName, "RDF:Description")) {
  269.         if (containerTagp(f, elementName)) {
  270.           setContainerp(obj, 1);
  271.         } else {
  272.           RDF_Resource eln = ResourceFromElementName(f, elementName);
  273.           addSlotValue(f, obj, gCoreVocab->RDF_instanceOf, eln, RDF_RESOURCE_TYPE, 1);
  274.         }
  275.       }
  276.       if (f->depth > 1) {
  277.         addSlotValue(f, f->stack[f->depth-2], f->stack[f->depth-1], obj, 
  278.                      RDF_RESOURCE_TYPE, 1);
  279.       }
  280.       if (!emptyElementp) {
  281.         f->stack[f->depth++] = obj;
  282.         f->status = EXPECTING_PROPERTY;
  283.       }
  284.     } else if (f->status == EXPECTING_PROPERTY) {
  285.       char* url;
  286.       RDF_Resource obj;
  287.       uint16 count = 0;
  288.       url = getHref(attlist) ;      
  289.       if (url) {
  290.         RDF_Resource eln = ResourceFromElementName(f, elementName);
  291.         url = possiblyMakeAbsolute(f, url);
  292.         obj =  RDF_GetResource(NULL, url, true);
  293.         freeMem(url);
  294.         addElementProps (attlist, elementName, f, obj) ;
  295.         addToResourceList(f, obj);
  296.         addSlotValue(f, f->stack[f->depth-1], eln,obj,RDF_RESOURCE_TYPE, 1);
  297.  
  298.       }
  299.       if (!emptyElementp) {
  300.         f->stack[f->depth++] = RDF_GetResource(NULL, elementName, 1);
  301.         f->status = EXPECTING_OBJECT;
  302.       }
  303.     }
  304.   }
  305. }    
  306.  
  307.  
  308.  
  309. void
  310. tokenizeElement (char* attr, char** attlist, char** elementName)
  311. {
  312.   size_t n = 1;
  313.   size_t s = strlen(attr); 
  314.   char c ;
  315.   size_t m = 0;
  316.   size_t atc = 0;
  317.   PRBool emptyTagp =  (attr[s-2] == '/');
  318.   PRBool inAttrNamep = 1;
  319.   c = attr[n++]; 
  320.   while (wsc(c)) {
  321.     c = attr[n++];
  322.   }
  323.   *elementName = &attr[n-1];
  324.   while (n < s) {
  325.     if (wsc(c)) break;
  326.     c = attr[n++];
  327.   }
  328.   attr[n-1] = '\0';
  329.   while (atc < 2*MAX_ATTRIBUTES+1) {*(attlist + atc++) = NULL;}
  330.   atc = 0;
  331.   s = (emptyTagp ? s-2 : s-1);
  332.   while (n < s) {
  333.     PRBool attributeOpenStringSeenp = 0;
  334.     m = 0;
  335.     c = attr[n++];
  336.     while ((n <= s) && (atc < 2*MAX_ATTRIBUTES)) {
  337.       if (inAttrNamep && (m > 0) && (wsc(c) || (c == '='))) {
  338.     attr[n-1] = '\0';
  339.     *(attlist + atc++) = &attr[n-m-1];
  340.     break;
  341.       }
  342.       if  (!inAttrNamep && attributeOpenStringSeenp && (c == '"')) {
  343.     attr[n-1] = '\0';
  344.     *(attlist + atc++) = &attr[n-m-1];
  345.     break;
  346.       }
  347.       if (inAttrNamep) {
  348.     if ((m > 0) || (!wsc(c))) m++;
  349.       } else {
  350.     if (c == '"') {
  351.       attributeOpenStringSeenp = 1;
  352.     } else {
  353.       if ((m > 0) || (!(wsc(c)))) m++;
  354.     }
  355.       }
  356.       c = attr[n++];
  357.     }
  358.     inAttrNamep = (inAttrNamep ? 0 : 1);
  359.   }
  360. }
  361.  
  362.  
  363.  
  364. void
  365. outputRDFTreeInt (RDF rdf, PRFileDesc *fp, RDF_Resource node, uint32 depth, PRBool localOnly) 
  366. {
  367.   RDF_Cursor c = RDF_GetSources(rdf, node, gCoreVocab->RDF_parent, RDF_RESOURCE_TYPE,  true);
  368.   RDF_Resource next;
  369.   char* buf = getMem(1024);
  370.   char* space = getMem((4*depth)+1);
  371.   char* url   = resourceID(node);
  372.   char* name  = RDF_GetResourceName(rdf, node);
  373.   char* hrefid;
  374.  
  375.   if ((buf == NULL) || (space == NULL)) return;
  376.   if (depth > 0) memset(space, ' ', depth);
  377.   
  378.   if (!strchr(url, ':') || (depth == 0)) {
  379.       hrefid = "id";
  380.   } else {
  381.       hrefid = "rdf:href";
  382.   }
  383.  
  384.   if (depth == 0) url="root";
  385.  
  386.   if (containerp(node)) {
  387.     if (depth > 0) {
  388.       sprintf(buf, "%s<child>\n", space);  
  389.       PR_Write(fp, buf, strlen(buf)); 
  390.     }
  391.     sprintf(buf, "%s<Topic %s=\"%s\"\n%s       name=\"%s\">\n", space, hrefid, url, space,   name);  
  392.     PR_Write(fp, buf, strlen(buf));
  393.     
  394.     while (next = RDF_NextValue(c)) {
  395.     
  396.       /* if exporting EVERYTHING, need to skip over certain things */
  397.       if ((localOnly == PR_FALSE) || ((!startsWith("ftp:",url)) && (!startsWith("file:",url))
  398.         && (!startsWith("IMAP:", url)) && (!startsWith("nes:", url))
  399.         && (!startsWith("mail:", url)) && (!startsWith("cache:", url))
  400.         && (!startsWith("ldap:", url)) &&
  401.         (!urlEquals(resourceID(node), resourceID(gNavCenter->RDF_LocalFiles))) &&
  402.         (!urlEquals(resourceID(node), resourceID(gNavCenter->RDF_History)))))
  403.     {
  404.         outputRDFTreeInt(rdf, fp, next, depth+1, localOnly);
  405.     }
  406.     }
  407.     sprintf(buf, "%s</Topic>\n", space);
  408.     PR_Write(fp, buf, strlen(buf));
  409.     if (depth > 0) {
  410.       sprintf(buf, "%s</child>\n", space);
  411.       PR_Write(fp, buf, strlen(buf));
  412.     } 
  413.   } else {
  414.     sprintf(buf, "%s<child %s=\"%s\"\n%s       name=\"%s\"/>\n", space, hrefid, url, space,   name); 
  415.     PR_Write(fp, buf, strlen(buf));
  416.   }
  417.   RDF_DisposeCursor(c);
  418.   freeMem(buf);
  419.   freeMem(space);
  420. }
  421.  
  422.  
  423.  
  424. void
  425. outputRDFTree (RDF rdf, PRFileDesc *fp, RDF_Resource node)
  426. {
  427.   ht_fprintf(fp, "<RDF:RDF>\n\n"); 
  428.   outputRDFTreeInt(rdf, fp, node, 0, (node==gNavCenter->RDF_Top) ? PR_TRUE:PR_FALSE);
  429.   ht_fprintf(fp, "\n</RDF:RDF>\n");
  430. }
  431.