diff --git a/modules/rdf/src/atalk.c b/modules/rdf/src/atalk.c new file mode 100644 index 00000000000..87149e5aef2 --- /dev/null +++ b/modules/rdf/src/atalk.c @@ -0,0 +1,576 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + This file implements (Mac) Appletalk support for the rdf data model. + For more information on this file, contact rjc or guha + For more information on RDF, look at the RDF section of www.mozilla.org +*/ + +#include "atalk.h" + + /* externs */ +void startAsyncCursors(); +void stopAsyncCursors(); + + + /* globals */ +static PRHashTable *atalk2rdfHash; +static PRHashTable *invatalk2rdfHash; +static RDFT gRDFDB = NULL; + + + +void +getZones() +{ + XPPParamBlock xBlock; + OSErr err = noErr; + + startAsyncCursors(); + + XP_BZERO(&xBlock, sizeof(xBlock)); + xBlock.XCALL.xppTimeout = 3; + xBlock.XCALL.xppRetry = 4; + xBlock.XCALL.zipBuffPtr = getMem(578); + xBlock.XCALL.zipLastFlag = 0; + xBlock.XCALL.zipInfoField[0] = 0; + xBlock.XCALL.zipInfoField[1] = 0; + while ((err == noErr) && (xBlock.XCALL.zipBuffPtr != NULL) && (!xBlock.XCALL.zipLastFlag)) + { + err = GetZoneList(&xBlock, FALSE); + if (!err) + { + processZones(xBlock.XCALL.zipBuffPtr, xBlock.XCALL.zipNumZones); + } + } + if (xBlock.XCALL.zipBuffPtr != NULL) + { + freeMem(xBlock.XCALL.zipBuffPtr); + xBlock.XCALL.zipBuffPtr = NULL; + } + + stopAsyncCursors(); +} + + + +void +processZones(char *zones, uint16 numZones) +{ + RDF_Resource r, parent; + char *escapedURL, url[1024], virtualURL[1024], *p; + uint16 loop; + + XP_ASSERT(zones != NULL); + if (zones == NULL) return; + + for (loop=0; loopRDF_Appletalk; + + XP_SPRINTF(url, zones+1, (unsigned)zones[0]); + url[(unsigned)zones[0]] = '\0'; + + p = url; + while (p != NULL) + { + p = XP_STRCHR(p, ' '); + if (p != NULL) *p = '\0'; + escapedURL = NET_Escape(url, URL_XALPHAS); /* URL_PATH */ + if (escapedURL == NULL) return; + if (p != NULL) *p++ = ' '; + + virtualURL[0] = '\0'; + if (p != NULL) XP_STRCAT(virtualURL, "virtual"); + XP_STRCAT(virtualURL, "zone://"); + XP_STRCAT(virtualURL, escapedURL); + XP_FREE(escapedURL); + + if ((r = RDF_GetResource(NULL, virtualURL, PR_TRUE)) != NULL) + { + if (startsWith("zone://", virtualURL)) + { + setResourceType(r, ATALK_RT); + } + else + { + setResourceType(r, ATALKVIRTUAL_RT); + } + } + if (r == NULL) break; + + setContainerp(r, PR_TRUE); + AtalkAdd(gRDFDB, r, gCoreVocab->RDF_parent, + parent, RDF_RESOURCE_TYPE); + parent = r; + } + +#if 0 XP_SPRINTF(url, "zone://"); + XP_STRNCAT(url, zones+1, (unsigned)zones[0]); + p = &url[7]; + + parent = gNavCenter->RDF_Appletalk; + while (p != NULL) + { + r = NULL; + if ((q = XP_STRCHR(p,' '))) + { + *q = '\0'; + escapedURL = NET_Escape(url + strlen("zone://"), URL_XALPHAS); /* URL_PATH */ + if (escapedURL != NULL) + { + strcpy(virtualUrl, "virtualzone://"); + strcat(virtualUrl, escapedURL); + if ((r = RDF_GetResource(NULL, escapedURL, PR_TRUE)) != NULL) + { + setResourceType(r, ATALKVIRTUAL_RT); + } + XP_FREE(escapedURL); + } + } + else + { + escapedURL = NET_Escape(url + strlen("zone://"), URL_XALPHAS); /* URL_PATH */ + if (escapedURL != NULL) + { + strcpy(virtualUrl, "zone://"); + strcat(virtualUrl, escapedURL); + if ((r = RDF_GetResource(NULL, virtualUrl, PR_TRUE)) != NULL) + { + setResourceType(r, ATALK_RT); + } + XP_FREE(escapedURL); + } + q = NULL; + } + if (r == NULL) break; + + setContainerp(r, PR_TRUE); + AtalkAdd(gRDFDB, r, gCoreVocab->RDF_parent, + parent, RDF_RESOURCE_TYPE); + parent = r; + + if (q == NULL) break; + *q++ = ' '; + p=q; + } +#endif + + zones += (1 + (unsigned)zones[0]); + } +} + + + +void +checkServerLookup (MPPParamBlock *nbp) +{ + AddrBlock address; + EntityName entity; + RDF_Resource r, parent; + char *escapedURL, afpUrl[128], url[128]; + uint16 loop; + OSErr err; + + if (nbp != NULL) + { + switch(nbp->MPPioResult) + { + case 1: + /* poll once a second */ + FE_SetTimeout((void *)checkServerLookup, (void *)nbp, 1000); + break; + + case 0: + for (loop=0; loopNBPnumGotten; loop++) + { + err = NBPExtract(nbp->NBPretBuffPtr, nbp->NBPnumGotten, loop, &entity, &address); + if (!err) + { + strncpy(url, &((char *)&entity)[1], ((char *)&entity)[0]); + url[((char *)&entity)[0]] = '\0'; + escapedURL = NET_Escape(url, URL_XALPHAS); /* URL_PATH */ + if (escapedURL != NULL) + { + strcpy(afpUrl, "afp://"); + strcat(afpUrl, escapedURL); + strcat(afpUrl, ":AFPServer@"); + strcat(afpUrl, ((char *)nbp->NBP.userData) + strlen("zone://")); + + if ((parent = RDF_GetResource(NULL, (char *)(nbp->NBP.userData), PR_TRUE)) != NULL) + { + if ((r = RDF_GetResource(NULL, afpUrl, PR_TRUE)) != NULL) + { + setResourceType(r, ATALK_RT); + AtalkAdd(gRDFDB, r, gCoreVocab->RDF_parent, + parent, RDF_RESOURCE_TYPE); + } + } + XP_FREE(escapedURL); + } + } + } + /* note: no "break" here! If operation finished (success or failure), free up memory */ + + default: + if (nbp->NBPretBuffPtr != NULL) freeMem(nbp->NBPretBuffPtr); + if (nbp->NBPentityPtr != NULL) freeMem(nbp->NBPentityPtr); + if (nbp->NBP.userData != NULL) freeMem((char *)nbp->NBP.userData); + freeMem(nbp); + break; + } + } +} + + + +void +getServers(RDF_Resource parent) +{ + EntityName *entity; + MPPParamBlock *nbp; + OSErr err = noErr; + char *buffer, *parentID, *zone, url[128]; + + if (!startsWith("zone://", resourceID(parent))) return; + + nbp = (MPPParamBlock *)getMem(sizeof(MPPParamBlock)); + entity = (EntityName *)getMem(sizeof(EntityName)); + buffer = getMem(10240); + zone = unescapeURL(resourceID(parent)+strlen("zone://")); + parentID = copyString(resourceID(parent)); + + if ((nbp != NULL) && (entity != NULL) && (buffer != NULL) && (zone != NULL) && (parentID != NULL)) + { + url[0] = strlen(zone); + strcpy(&url[1], zone); + NBPSetEntity((char *)entity, "\p=", "\pAFPServer", (void *)url); + nbp->MPPioCompletion = NULL; + nbp->NBPinterval = 5; + nbp->NBPcount = 3; + nbp->NBPentityPtr = (char *)entity; + nbp->NBPretBuffPtr = buffer; + nbp->NBPretBuffSize = 10240; + nbp->NBPmaxToGet = 256; + nbp->NBP.userData = (long)parentID; + err = PLookupName(nbp, TRUE); + + /* poll once a second */ + FE_SetTimeout((void *)checkServerLookup, (void *)nbp, 1000); + } + if (err < 0) + { + if (nbp != NULL) freeMem(nbp); + if (zone != NULL) freeMem(zone); + if (buffer != NULL) freeMem(buffer); + if (parentID != NULL) freeMem(parentID); + } +} + + + +Assertion +atalkarg1 (RDF_Resource u) +{ + return (Assertion) PR_HashTableLookup(atalk2rdfHash, u); +} + + + +Assertion +setatalkarg1 (RDF_Resource u, Assertion as) +{ + return (Assertion) PR_HashTableAdd(atalk2rdfHash, u, as); +} + + + +Assertion +atalkarg2 (RDF_Resource u) +{ + return (Assertion) PR_HashTableLookup(invatalk2rdfHash, u); +} + + + +Assertion +setatalkarg2 (RDF_Resource u, Assertion as) +{ + return (Assertion) PR_HashTableAdd(invatalk2rdfHash, u, as); +} + + + +PRBool +AtalkHasAssertion (RDFT rdf, RDF_Resource u, RDF_Resource s, void* v, + RDF_ValueType type, PRBool tv) +{ + Assertion nextAs; + + if (startsWith("zone://", resourceID(u))) + { + nextAs = atalkarg1(u); + while (nextAs != null) + { + if (asEqual(nextAs, u, s, v, type) && (nextAs->tv == tv)) return true; + nextAs = nextAs->next; + } + + if (s == gCoreVocab->RDF_parent || s == gCoreVocab->RDF_child) + { + if (atalkarg1(u) == NULL) + { + getServers(u); + } + } + + nextAs = atalkarg1(u); + while (nextAs != null) + { + if (asEqual(nextAs, u, s, v, type) && (nextAs->tv == tv)) return true; + nextAs = nextAs->next; + } + } + return(PR_FALSE); +} + + + +void * +AtalkGetSlotValue(RDFT rdf, RDF_Resource u, RDF_Resource s, RDF_ValueType type, + PRBool inversep, PRBool tv) +{ + void *val = NULL; + char *url; + + if (u == NULL) return(NULL); + + if ((s == gCoreVocab->RDF_name) && ((resourceType(u) == ATALK_RT) || + (resourceType(u) == ATALKVIRTUAL_RT)) && (type == RDF_STRING_TYPE) && (tv)) + { + if (u == gNavCenter->RDF_Appletalk) + { + /* XXX localization */ + + val = copyString("Appletalk Zones and File Servers"); + } + else if (startsWith("virtualzone://", resourceID(u))) + { + if ((url = unescapeURL(resourceID(u) + strlen("virtualzone://"))) != NULL) + { + if ((val = XP_STRRCHR(url, ' ')) != NULL) + { + val = copyString(((char *)val) + 1); + } + else + { + val = copyString(url); + } + freeMem(url); + } + } + else if (startsWith("zone://", resourceID(u))) + { + if ((url = unescapeURL(resourceID(u) + strlen("zone://"))) != NULL) + { + if ((val = XP_STRRCHR(url, ' ')) != NULL) + { + val = copyString(((char *)val) + 1); + } + else + { + val = copyString(url); + } + freeMem(url); + } + } + else if (startsWith("afp://", resourceID(u))) + { + if ((url = unescapeURL(resourceID(u) + strlen("afp://"))) != NULL) + { + if ((val = XP_STRRCHR(url, ':')) != NULL) + { + *(char *)val = '\0'; + } + val = copyString(url); + freeMem(url); + } + } + } + return(val); +} + + + +PRBool +AtalkAdd (RDFT rdf, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type) +{ + Assertion nextAs, prevAs, newAs; + + if ((s == gCoreVocab->RDF_instanceOf) && (v == gWebData->RDF_Container)) + { + setContainerp(u, true); + return 1; + } + nextAs = prevAs = u->rarg1; + while (nextAs != null) + { + if (asEqual(nextAs, u, s, v, type)) return 1; + prevAs = nextAs; + nextAs = nextAs->next; + } + newAs = makeNewAssertion(u, s, v, type, 1); + if (prevAs == null) + { + u->rarg1 = newAs; + } + else + { + prevAs->next = newAs; + } + if (type == RDF_RESOURCE_TYPE) + { + nextAs = prevAs = ((RDF_Resource)v)->rarg2; + while (nextAs != null) + { + prevAs = nextAs; + nextAs = nextAs->invNext; + } + if (prevAs == null) + { + ((RDF_Resource)v)->rarg2 = newAs; + } + else + { + prevAs->invNext = newAs; + } + } + sendNotifications2(rdf, RDF_INSERT_NOTIFY, u, s, v, type, 1); + return true; +} + + + +void * +AtalkNextValue (RDFT rdf, RDF_Cursor c) +{ + Assertion as; + + XP_ASSERT(c != NULL); + if (c == NULL) return(NULL); + + while (c->pdata != null) + { + as = (Assertion) c->pdata; + if ((as->s == c->s) && (as->tv == c->tv) && (c->type == as->type)) + { + c->value = (c->inversep ? as->u : as->value); + c->pdata = (c->inversep ? as->invNext : as->next); + return c->value; + } + c->pdata = (c->inversep ? as->invNext : as->next); + } + return(NULL); +} + + + +RDF_Cursor +AtalkGetSlotValues (RDFT rdf, RDF_Resource u, RDF_Resource s, + RDF_ValueType type, PRBool inversep, PRBool tv) +{ + Assertion as; + RDF_Cursor c = NULL; + + as = (inversep ? atalkarg2(u) : atalkarg1(u)); + if (as == null) + { + getServers(u); + + as = (inversep ? atalkarg2(u) : atalkarg1(u)); + if (as == null) + return null; + } + + if ((c = (RDF_Cursor)getMem(sizeof(struct RDF_CursorStruct))) != NULL) + { + c->u = u; + c->s = s; + c->value = NULL; + c->type = type; + c->inversep = inversep; + c->tv = tv; + c->count = 0; + } + return(c); +} + + + +RDF_Error +AtalkDisposeCursor (RDFT rdf, RDF_Cursor c) +{ + if (c != NULL) + { + freeMem(c); + } + return(0); +} + + + +RDF_Error +AtalkDestroy (RDFT r) +{ + /* XXX to do - kill of any outstanding NBP lookups */ +} + + + +RDFT +MakeAtalkStore (char* url) +{ + RDFT ntr = NULL; + + if (gRDFDB != NULL) return(gRDFDB); + + if (strstr(url, "rdf:appletalk")) + { + if ((ntr = (RDFT)getMem(sizeof(struct RDF_TranslatorStruct))) != NULL) + { + ntr->assert = NULL; + ntr->unassert = NULL; + ntr->hasAssertion = AtalkHasAssertion; + ntr->getSlotValue = AtalkGetSlotValue; + ntr->getSlotValues = AtalkGetSlotValues; + ntr->nextValue = AtalkNextValue; + ntr->disposeCursor = AtalkDisposeCursor; + ntr->destroy = AtalkDestroy; + ntr->url = copyString(url); + + atalk2rdfHash = PR_NewHashTable(500, idenHash, idenEqual, idenEqual, null, null); + invatalk2rdfHash = PR_NewHashTable(500, idenHash, idenEqual, idenEqual, null, null); + gRDFDB = ntr; + + getZones(); + } + + } + return(ntr); +} diff --git a/modules/rdf/src/atalk.h b/modules/rdf/src/atalk.h new file mode 100644 index 00000000000..7f8c7977a57 --- /dev/null +++ b/modules/rdf/src/atalk.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef _RDF_ATALK_H_ +#define _RDF_ATALK_H_ + + +#include +#include "rdf.h" +#include "rdf-int.h" +#include "mcf.h" +#include "vocab.h" +#include "utils.h" + + +/* atalk.c data structures and defines */ + + +/* atalk.c function prototypes */ + +XP_BEGIN_PROTOS + +void getZones(); +void processZones(char *zones, uint16 numZones); +void checkServerLookup (MPPParamBlock *nbp); +void getServers(RDF_Resource parent); +Assertion atalkarg1 (RDF_Resource u); +Assertion setatalkarg1 (RDF_Resource u, Assertion as); +Assertion atalkarg2 (RDF_Resource u); +Assertion setatalkarg2 (RDF_Resource u, Assertion as); +PRBool AtalkHasAssertion (RDFT rdf, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, PRBool tv); +void * AtalkGetSlotValue(RDFT rdf, RDF_Resource u, RDF_Resource s, RDF_ValueType type, PRBool inversep, PRBool tv); +PRBool AtalkAdd (RDFT rdf, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type); +void * AtalkNextValue (RDFT rdf, RDF_Cursor c); +RDF_Cursor AtalkGetSlotValues (RDFT rdf, RDF_Resource u, RDF_Resource s, RDF_ValueType type, PRBool inversep, PRBool tv); +RDF_Error AtalkDisposeCursor (RDFT rdf, RDF_Cursor c); +RDF_Error AtalkDestroy (RDFT r); +RDFT MakeAtalkStore (char* url); + +XP_END_PROTOS + +#endif