Changeset 640 for trunk/zoo-project/zoo-kernel/service_internal.c
- Timestamp:
- May 28, 2015, 4:25:06 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/zoo-project/zoo-kernel/service_internal.c
r634 r640 23 23 */ 24 24 25 #include "fcgi_stdio.h" 25 26 #include "service_internal.h" 26 #ifdef USE_MS27 #include "service_internal_ms.h"28 #else29 #include "cpl_vsi.h"30 #endif31 27 32 28 #ifndef TRUE … … 37 33 #endif 38 34 39 #ifndef WIN3240 #include <dlfcn.h>41 #endif42 43 35 #define ERROR_MSG_MAX_LENGTH 1024 44 45 #include "mimetypes.h"46 47 /**48 * Verify if a given language is listed in the lang list defined in the [main]49 * section of the main.cfg file.50 *51 * @param conf the map containing the settings from the main.cfg file52 * @param str the specific language53 * @return 1 if the specific language is listed, -1 in other case.54 */55 int isValidLang(maps* conf,const char *str){56 map *tmpMap=getMapFromMaps(conf,"main","lang");57 char *tmp=zStrdup(tmpMap->value);58 char *pToken=strtok(tmp,",");59 int res=-1;60 while(pToken!=NULL){61 if(strcasecmp(str,pToken)==0){62 res=1;63 break;64 }65 pToken = strtok(NULL,",");66 }67 free(tmp);68 return res;69 }70 71 /**72 * Print the HTTP headers based on a map.73 *74 * @param m the map containing the headers informations75 */76 void printHeaders(maps* m){77 maps *_tmp=getMaps(m,"headers");78 if(_tmp!=NULL){79 map* _tmp1=_tmp->content;80 while(_tmp1!=NULL){81 printf("%s: %s\r\n",_tmp1->name,_tmp1->value);82 _tmp1=_tmp1->next;83 }84 }85 }86 87 /**88 * Add a land attribute to a XML node89 *90 * @param n the XML node to add the attribute91 * @param m the map containing the language key to add as xml:lang92 */93 void addLangAttr(xmlNodePtr n,maps *m){94 map *tmpLmap=getMapFromMaps(m,"main","language");95 if(tmpLmap!=NULL)96 xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST tmpLmap->value);97 else98 xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en-US");99 }100 101 /**102 * Converts a hex character to its integer value103 *104 * @param ch the char to convert105 * @return the converted char106 */107 char from_hex(char ch) {108 return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;109 }110 111 /**112 * Converts an integer value to its hec character113 *114 * @param code the char to convert115 * @return the converted char116 */117 char to_hex(char code) {118 static char hex[] = "0123456789abcdef";119 return hex[code & 15];120 }121 36 122 37 /** … … 649 564 #endif 650 565 651 652 /**653 * URLEncode an url654 *655 * @param str the url to encode656 * @return a url-encoded version of str657 * @warning be sure to free() the returned string after use658 */659 char *url_encode(char *str) {660 char *pstr = str, *buf = (char*) malloc(strlen(str) * 3 + 1), *pbuf = buf;661 while (*pstr) {662 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')663 *pbuf++ = *pstr;664 else if (*pstr == ' ')665 *pbuf++ = '+';666 else667 *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);668 pstr++;669 }670 *pbuf = '\0';671 return buf;672 }673 674 /**675 * Decode an URLEncoded url676 *677 * @param str the URLEncoded url to decode678 * @return a url-decoded version of str679 * @warning be sure to free() the returned string after use680 */681 char *url_decode(char *str) {682 char *pstr = str, *buf = (char*) malloc(strlen(str) + 1), *pbuf = buf;683 while (*pstr) {684 if (*pstr == '%') {685 if (pstr[1] && pstr[2]) {686 *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);687 pstr += 2;688 }689 } else if (*pstr == '+') {690 *pbuf++ = ' ';691 } else {692 *pbuf++ = *pstr;693 }694 pstr++;695 }696 *pbuf = '\0';697 return buf;698 }699 700 /**701 * Replace the first letter by its upper case version in a new char array702 *703 * @param tmp the char*704 * @return a new char* with first letter in upper case705 * @warning be sure to free() the returned string after use706 */707 char *zCapitalize1(char *tmp){708 char *res=zStrdup(tmp);709 if(res[0]>=97 && res[0]<=122)710 res[0]-=32;711 return res;712 }713 714 /**715 * Replace all letters by their upper case version in a new char array716 *717 * @param tmp the char*718 * @return a new char* with first letter in upper case719 * @warning be sure to free() the returned string after use720 */721 char *zCapitalize(char *tmp){722 int i=0;723 char *res=zStrdup(tmp);724 for(i=0;i<strlen(res);i++)725 if(res[i]>=97 && res[i]<=122)726 res[i]-=32;727 return res;728 }729 730 /**731 * Search for an existing XML namespace in usedNS.732 *733 * @param name the name of the XML namespace to search734 * @return the index of the XML namespace found or -1 if not found.735 */736 int zooXmlSearchForNs(const char* name){737 int i;738 int res=-1;739 for(i=0;i<nbNs;i++)740 if(strncasecmp(name,nsName[i],strlen(nsName[i]))==0){741 res=i;742 break;743 }744 return res;745 }746 747 /**748 * Add an XML namespace to the usedNS if it was not already used.749 *750 * @param nr the xmlNodePtr to attach the XML namspace (can be NULL)751 * @param url the url of the XML namespace to add752 * @param name the name of the XML namespace to add753 * @return the index of the XML namespace added.754 */755 int zooXmlAddNs(xmlNodePtr nr,const char* url,const char* name){756 #ifdef DEBUG757 fprintf(stderr,"zooXmlAddNs %d %s \n",nbNs,name);758 #endif759 int currId=-1;760 if(nbNs==0){761 nbNs++;762 currId=0;763 nsName[currId]=strdup(name);764 usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);765 }else{766 currId=zooXmlSearchForNs(name);767 if(currId<0){768 nbNs++;769 currId=nbNs-1;770 nsName[currId]=strdup(name);771 usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);772 }773 }774 return currId;775 }776 777 /**778 * Free allocated memory to store used XML namespace.779 */780 void zooXmlCleanupNs(){781 int j;782 #ifdef DEBUG783 fprintf(stderr,"zooXmlCleanup %d\n",nbNs);784 #endif785 for(j=nbNs-1;j>=0;j--){786 #ifdef DEBUG787 fprintf(stderr,"zooXmlCleanup %d\n",j);788 #endif789 if(j==0)790 xmlFreeNs(usedNs[j]);791 free(nsName[j]);792 nbNs--;793 }794 nbNs=0;795 }796 797 /**798 * Add a XML document to the iDocs.799 *800 * @param value the string containing the XML document801 * @return the index of the XML document added.802 */803 int zooXmlAddDoc(const char* value){804 int currId=0;805 nbDocs++;806 currId=nbDocs-1;807 iDocs[currId]=xmlParseMemory(value,strlen(value));808 return currId;809 }810 811 /**812 * Free allocated memort to store XML documents813 */814 void zooXmlCleanupDocs(){815 int j;816 for(j=nbDocs-1;j>=0;j--){817 xmlFreeDoc(iDocs[j]);818 }819 nbDocs=0;820 }821 822 /**823 * Generate a SOAP Envelope node when required (if the isSoap key of the [main]824 * section is set to true).825 *826 * @param conf the conf maps containing the main.cfg settings827 * @param n the node used as children of the generated soap:Envelope828 * @return the generated soap:Envelope (if isSoap=true) or the input node n829 * (when isSoap=false)830 */831 xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){832 map* soap=getMapFromMaps(conf,"main","isSoap");833 if(soap!=NULL && strcasecmp(soap->value,"true")==0){834 int lNbNs=nbNs;835 nsName[lNbNs]=strdup("soap");836 usedNs[lNbNs]=xmlNewNs(NULL,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");837 nbNs++;838 xmlNodePtr nr = xmlNewNode(usedNs[lNbNs], BAD_CAST "Envelope");839 nsName[nbNs]=strdup("soap");840 usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");841 nbNs++;842 nsName[nbNs]=strdup("xsi");843 usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");844 nbNs++;845 xmlNsPtr ns_xsi=usedNs[nbNs-1];846 xmlNewNsProp(nr,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.w3.org/2003/05/soap-envelope http://www.w3.org/2003/05/soap-envelope");847 xmlNodePtr nr1 = xmlNewNode(usedNs[lNbNs], BAD_CAST "Body");848 xmlAddChild(nr1,n);849 xmlAddChild(nr,nr1);850 return nr;851 }else852 return n;853 }854 855 /**856 * Generate a WPS header.857 *858 * @param doc the document to add the header859 * @param m the conf maps containing the main.cfg settings860 * @param req the request type (GetCapabilities,DescribeProcess,Execute)861 * @param rname the root node name862 * @return the generated wps:rname xmlNodePtr (can be wps: Capabilities,863 * wps:ProcessDescriptions,wps:ExecuteResponse)864 */865 xmlNodePtr printWPSHeader(xmlDocPtr doc,maps* m,const char* req,const char* rname){866 867 xmlNsPtr ns,ns_xsi;868 xmlNodePtr n;869 870 int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");871 ns=usedNs[wpsId];872 n = xmlNewNode(ns, BAD_CAST rname);873 zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");874 xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");875 zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");876 int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");877 ns_xsi=usedNs[xsiId];878 879 char *tmp=(char*) malloc((86+strlen(req)+1)*sizeof(char));880 sprintf(tmp,"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wps%s_response.xsd",req);881 xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);882 free(tmp);883 xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");884 xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");885 addLangAttr(n,m);886 xmlNodePtr fn=soapEnvelope(m,n);887 xmlDocSetRootElement(doc, fn);888 return n;889 }890 891 /**892 * Generate a Capabilities header.893 *894 * @param doc the document to add the header895 * @param m the conf maps containing the main.cfg settings896 * @return the generated wps:ProcessOfferings xmlNodePtr897 */898 xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,maps* m){899 900 xmlNsPtr ns,ns_ows,ns_xlink;901 xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6;902 n = printWPSHeader(doc,m,"GetCapabilities","Capabilities");903 maps* toto1=getMaps(m,"main");904 char tmp[256];905 906 int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");907 ns=usedNs[wpsId];908 int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");909 ns_xlink=usedNs[xlinkId];910 int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");911 ns_ows=usedNs[owsId];912 913 nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");914 maps* tmp4=getMaps(m,"identification");915 if(tmp4!=NULL){916 map* tmp2=tmp4->content;917 const char *orderedFields[5];918 orderedFields[0]="Title";919 orderedFields[1]="Abstract";920 orderedFields[2]="Keywords";921 orderedFields[3]="Fees";922 orderedFields[4]="AccessConstraints";923 int oI=0;924 for(oI=0;oI<5;oI++)925 if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){926 if(strcasecmp(tmp2->name,"abstract")==0 ||927 strcasecmp(tmp2->name,"title")==0 ||928 strcasecmp(tmp2->name,"accessConstraints")==0 ||929 strcasecmp(tmp2->name,"fees")==0){930 tmp2->name[0]=toupper(tmp2->name[0]);931 nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);932 xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));933 xmlAddChild(nc,nc1);934 }935 else936 if(strcmp(tmp2->name,"keywords")==0){937 nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");938 char *toto=tmp2->value;939 char buff[256];940 int i=0;941 int j=0;942 while(toto[i]){943 if(toto[i]!=',' && toto[i]!=0){944 buff[j]=toto[i];945 buff[j+1]=0;946 j++;947 }948 else{949 nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");950 xmlAddChild(nc2,xmlNewText(BAD_CAST buff));951 xmlAddChild(nc1,nc2);952 j=0;953 }954 i++;955 }956 if(strlen(buff)>0){957 nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");958 xmlAddChild(nc2,xmlNewText(BAD_CAST buff));959 xmlAddChild(nc1,nc2);960 }961 xmlAddChild(nc,nc1);962 nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceType");963 xmlAddChild(nc2,xmlNewText(BAD_CAST "WPS"));964 xmlAddChild(nc,nc2);965 nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceTypeVersion");966 xmlAddChild(nc2,xmlNewText(BAD_CAST "1.0.0"));967 xmlAddChild(nc,nc2);968 }969 tmp2=tmp2->next;970 }971 }972 else{973 fprintf(stderr,"TMP4 NOT FOUND !!");974 return NULL;975 }976 xmlAddChild(n,nc);977 978 nc = xmlNewNode(ns_ows, BAD_CAST "ServiceProvider");979 nc3 = xmlNewNode(ns_ows, BAD_CAST "ServiceContact");980 nc4 = xmlNewNode(ns_ows, BAD_CAST "ContactInfo");981 nc5 = xmlNewNode(ns_ows, BAD_CAST "Phone");982 nc6 = xmlNewNode(ns_ows, BAD_CAST "Address");983 tmp4=getMaps(m,"provider");984 if(tmp4!=NULL){985 map* tmp2=tmp4->content;986 const char *tmpAddress[6];987 tmpAddress[0]="addressDeliveryPoint";988 tmpAddress[1]="addressCity";989 tmpAddress[2]="addressAdministrativeArea";990 tmpAddress[3]="addressPostalCode";991 tmpAddress[4]="addressCountry";992 tmpAddress[5]="addressElectronicMailAddress";993 const char *tmpPhone[2];994 tmpPhone[0]="phoneVoice";995 tmpPhone[1]="phoneFacsimile";996 const char *orderedFields[12];997 orderedFields[0]="providerName";998 orderedFields[1]="providerSite";999 orderedFields[2]="individualName";1000 orderedFields[3]="positionName";1001 orderedFields[4]=tmpPhone[0];1002 orderedFields[5]=tmpPhone[1];1003 orderedFields[6]=tmpAddress[0];1004 orderedFields[7]=tmpAddress[1];1005 orderedFields[8]=tmpAddress[2];1006 orderedFields[9]=tmpAddress[3];1007 orderedFields[10]=tmpAddress[4];1008 orderedFields[11]=tmpAddress[5];1009 int oI=0;1010 for(oI=0;oI<12;oI++)1011 if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){1012 if(strcmp(tmp2->name,"keywords")!=0 &&1013 strcmp(tmp2->name,"serverAddress")!=0 &&1014 strcmp(tmp2->name,"lang")!=0){1015 tmp2->name[0]=toupper(tmp2->name[0]);1016 if(strcmp(tmp2->name,"ProviderName")==0){1017 nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);1018 xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));1019 xmlAddChild(nc,nc1);1020 }1021 else{1022 if(strcmp(tmp2->name,"ProviderSite")==0){1023 nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);1024 xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST tmp2->value);1025 xmlAddChild(nc,nc1);1026 }1027 else1028 if(strcmp(tmp2->name,"IndividualName")==0 ||1029 strcmp(tmp2->name,"PositionName")==0){1030 nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);1031 xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));1032 xmlAddChild(nc3,nc1);1033 }1034 else1035 if(strncmp(tmp2->name,"Phone",5)==0){1036 int j;1037 for(j=0;j<2;j++)1038 if(strcasecmp(tmp2->name,tmpPhone[j])==0){1039 char *tmp4=tmp2->name;1040 nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+5);1041 xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));1042 xmlAddChild(nc5,nc1);1043 }1044 }1045 else1046 if(strncmp(tmp2->name,"Address",7)==0){1047 int j;1048 for(j=0;j<6;j++)1049 if(strcasecmp(tmp2->name,tmpAddress[j])==0){1050 char *tmp4=tmp2->name;1051 nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+7);1052 xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));1053 xmlAddChild(nc6,nc1);1054 }1055 }1056 }1057 }1058 else1059 if(strcmp(tmp2->name,"keywords")==0){1060 nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");1061 char *toto=tmp2->value;1062 char buff[256];1063 int i=0;1064 int j=0;1065 while(toto[i]){1066 if(toto[i]!=',' && toto[i]!=0){1067 buff[j]=toto[i];1068 buff[j+1]=0;1069 j++;1070 }1071 else{1072 nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");1073 xmlAddChild(nc2,xmlNewText(BAD_CAST buff));1074 xmlAddChild(nc1,nc2);1075 j=0;1076 }1077 i++;1078 }1079 if(strlen(buff)>0){1080 nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");1081 xmlAddChild(nc2,xmlNewText(BAD_CAST buff));1082 xmlAddChild(nc1,nc2);1083 }1084 xmlAddChild(nc,nc1);1085 }1086 tmp2=tmp2->next;1087 }1088 }1089 else{1090 fprintf(stderr,"TMP4 NOT FOUND !!");1091 }1092 xmlAddChild(nc4,nc5);1093 xmlAddChild(nc4,nc6);1094 xmlAddChild(nc3,nc4);1095 xmlAddChild(nc,nc3);1096 xmlAddChild(n,nc);1097 1098 1099 nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");1100 char *tmp2[3];1101 tmp2[0]=strdup("GetCapabilities");1102 tmp2[1]=strdup("DescribeProcess");1103 tmp2[2]=strdup("Execute");1104 int j=0;1105 1106 if(toto1!=NULL){1107 map* tmp=getMap(toto1->content,"serverAddress");1108 if(tmp!=NULL){1109 SERVICE_URL = strdup(tmp->value);1110 }1111 else1112 SERVICE_URL = strdup("not_defined");1113 }1114 else1115 SERVICE_URL = strdup("not_defined");1116 1117 for(j=0;j<3;j++){1118 nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");1119 xmlNewProp(nc1,BAD_CAST "name",BAD_CAST tmp2[j]);1120 nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");1121 nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");1122 nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");1123 sprintf(tmp,"%s",SERVICE_URL);1124 xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST tmp);1125 xmlAddChild(nc3,nc4);1126 nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");1127 xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST tmp);1128 xmlAddChild(nc3,nc4);1129 xmlAddChild(nc2,nc3);1130 xmlAddChild(nc1,nc2);1131 xmlAddChild(nc,nc1);1132 }1133 for(j=2;j>=0;j--)1134 free(tmp2[j]);1135 xmlAddChild(n,nc);1136 1137 nc = xmlNewNode(ns, BAD_CAST "ProcessOfferings");1138 xmlAddChild(n,nc);1139 1140 nc1 = xmlNewNode(ns, BAD_CAST "Languages");1141 nc2 = xmlNewNode(ns, BAD_CAST "Default");1142 nc3 = xmlNewNode(ns, BAD_CAST "Supported");1143 1144 toto1=getMaps(m,"main");1145 if(toto1!=NULL){1146 map* tmp1=getMap(toto1->content,"lang");1147 char *toto=tmp1->value;1148 char buff[256];1149 int i=0;1150 int j=0;1151 int dcount=0;1152 while(toto[i]){1153 if(toto[i]!=',' && toto[i]!=0){1154 buff[j]=toto[i];1155 buff[j+1]=0;1156 j++;1157 }1158 else{1159 nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");1160 xmlAddChild(nc4,xmlNewText(BAD_CAST buff));1161 if(dcount==0){1162 xmlAddChild(nc2,nc4);1163 xmlAddChild(nc1,nc2);1164 dcount++;1165 }1166 nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");1167 xmlAddChild(nc4,xmlNewText(BAD_CAST buff));1168 xmlAddChild(nc3,nc4);1169 j=0;1170 buff[j]=0;1171 }1172 i++;1173 }1174 if(strlen(buff)>0){1175 nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");1176 xmlAddChild(nc4,xmlNewText(BAD_CAST buff));1177 xmlAddChild(nc3,nc4);1178 }1179 }1180 xmlAddChild(nc1,nc3);1181 xmlAddChild(n,nc1);1182 1183 free(SERVICE_URL);1184 return nc;1185 }1186 1187 /**1188 * Add prefix to the service name.1189 *1190 * @param conf the conf maps containing the main.cfg settings1191 * @param level the map containing the level information1192 * @param serv the service structure created from the zcfg file1193 */1194 void addPrefix(maps* conf,map* level,service* serv){1195 if(level!=NULL){1196 char key[25];1197 char* prefix=NULL;1198 int clevel=atoi(level->value);1199 int cl=0;1200 for(cl=0;cl<clevel;cl++){1201 sprintf(key,"sprefix_%d",cl);1202 map* tmp2=getMapFromMaps(conf,"lenv",key);1203 if(tmp2!=NULL){1204 if(prefix==NULL)1205 prefix=zStrdup(tmp2->value);1206 else{1207 int plen=strlen(prefix);1208 prefix=(char*)realloc(prefix,(plen+strlen(tmp2->value)+2)*sizeof(char));1209 memcpy(prefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char));1210 prefix[plen+strlen(tmp2->value)]=0;1211 }1212 }1213 }1214 if(prefix!=NULL){1215 char* tmp0=strdup(serv->name);1216 free(serv->name);1217 serv->name=(char*)malloc((strlen(prefix)+strlen(tmp0)+1)*sizeof(char));1218 sprintf(serv->name,"%s%s",prefix,tmp0);1219 free(tmp0);1220 free(prefix);1221 prefix=NULL;1222 }1223 }1224 }1225 1226 /**1227 * Generate a wps:Process node for a servie and add it to a given node.1228 *1229 * @param m the conf maps containing the main.cfg settings1230 * @param registry the profile registry if any1231 * @param nc the XML node to add the Process node1232 * @param serv the service structure created from the zcfg file1233 * @return the generated wps:ProcessOfferings xmlNodePtr1234 */1235 void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){1236 xmlNsPtr ns,ns_ows,ns_xlink;1237 xmlNodePtr n=NULL,nc1,nc2;1238 /**1239 * Initialize or get existing namspaces1240 */1241 int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");1242 ns=usedNs[wpsId];1243 int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");1244 ns_ows=usedNs[owsId];1245 int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");1246 ns_xlink=usedNs[xlinkId];1247 1248 map* tmp1;1249 if(serv->content!=NULL){1250 nc1 = xmlNewNode(ns, BAD_CAST "Process");1251 tmp1=getMap(serv->content,"processVersion");1252 if(tmp1!=NULL)1253 xmlNewNsProp(nc1,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);1254 else1255 xmlNewNsProp(nc1,ns,BAD_CAST "processVersion",BAD_CAST "1");1256 map* tmp3=getMapFromMaps(m,"lenv","level");1257 addPrefix(m,tmp3,serv);1258 printDescription(nc1,ns_ows,serv->name,serv->content);1259 tmp1=serv->metadata;1260 while(tmp1!=NULL){1261 nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");1262 xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);1263 xmlAddChild(nc1,nc2);1264 tmp1=tmp1->next;1265 }1266 xmlAddChild(nc,nc1);1267 }1268 }1269 1270 /**1271 * Generate a ProcessDescription node for a servie and add it to a given node.1272 *1273 * @param m the conf maps containing the main.cfg settings1274 * @param nc the XML node to add the Process node1275 * @param serv the servive structure created from the zcfg file1276 * @return the generated wps:ProcessOfferings xmlNodePtr1277 */1278 void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service* serv){1279 xmlNsPtr ns,ns_ows,ns_xlink;1280 xmlNodePtr n,nc1;1281 1282 n=nc;1283 1284 int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");1285 ns=usedNs[wpsId];1286 int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");1287 ns_ows=usedNs[owsId];1288 int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");1289 ns_xlink=usedNs[xlinkId];1290 1291 nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");1292 const char *tmp4[3];1293 tmp4[0]="processVersion";1294 tmp4[1]="storeSupported";1295 tmp4[2]="statusSupported";1296 int j=0;1297 map* tmp1=NULL;1298 for(j=0;j<3;j++){1299 tmp1=getMap(serv->content,tmp4[j]);1300 if(tmp1!=NULL){1301 if(j==0)1302 xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);1303 else1304 xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);1305 }1306 else{1307 if(j>0)1308 xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "true");1309 else1310 xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST "1");1311 }1312 }1313 1314 tmp1=getMapFromMaps(m,"lenv","level");1315 addPrefix(m,tmp1,serv);1316 printDescription(nc,ns_ows,serv->name,serv->content);1317 1318 tmp1=serv->metadata;1319 while(tmp1!=NULL){1320 nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");1321 xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);1322 xmlAddChild(nc,nc1);1323 tmp1=tmp1->next;1324 }1325 1326 tmp1=getMap(serv->content,"Profile");1327 if(tmp1!=NULL){1328 nc1 = xmlNewNode(ns, BAD_CAST "Profile");1329 xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));1330 xmlAddChild(nc,nc1);1331 }1332 1333 if(serv->inputs!=NULL){1334 nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");1335 elements* e=serv->inputs;1336 printFullDescription(1,e,"Input",ns_ows,nc1);1337 xmlAddChild(nc,nc1);1338 }1339 1340 nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");1341 elements* e=serv->outputs;1342 printFullDescription(0,e,"Output",ns_ows,nc1);1343 xmlAddChild(nc,nc1);1344 1345 xmlAddChild(n,nc);1346 1347 }1348 1349 /**1350 * Generate the required XML tree for the detailled metadata informations of1351 * inputs or outputs1352 *1353 * @param in 1 in case of inputs, 0 for outputs1354 * @param elem the elements structure containing the metadata informations1355 * @param type the name ("Input" or "Output") of the XML node to create1356 * @param ns_ows the ows XML namespace1357 * @param nc1 the XML node to use to add the created tree1358 */1359 void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns_ows,xmlNodePtr nc1){1360 const char *orderedFields[13];1361 orderedFields[0]="mimeType";1362 orderedFields[1]="encoding";1363 orderedFields[2]="schema";1364 orderedFields[3]="dataType";1365 orderedFields[4]="uom";1366 orderedFields[5]="CRS";1367 orderedFields[6]="value";1368 orderedFields[7]="AllowedValues";1369 orderedFields[8]="range";1370 orderedFields[9]="rangeMin";1371 orderedFields[10]="rangeMax";1372 orderedFields[11]="rangeClosure";1373 orderedFields[12]="rangeSpace";1374 1375 xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9;1376 elements* e=elem;1377 1378 map* tmp1=NULL;1379 while(e!=NULL){1380 int default1=0;1381 int isAnyValue=1;1382 nc2 = xmlNewNode(NULL, BAD_CAST type);1383 if(strncmp(type,"Input",5)==0){1384 tmp1=getMap(e->content,"minOccurs");1385 if(tmp1!=NULL){1386 xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);1387 }else1388 xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0");1389 tmp1=getMap(e->content,"maxOccurs");1390 if(tmp1!=NULL){1391 if(strcasecmp(tmp1->value,"unbounded")!=0)1392 xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);1393 else1394 xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000");1395 }else1396 xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1");1397 if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){1398 xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value);1399 }1400 }1401 1402 printDescription(nc2,ns_ows,e->name,e->content);1403 1404 /**1405 * Build the (Literal/Complex/BoundingBox)Data node1406 */1407 if(strncmp(type,"Output",6)==0){1408 if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)1409 nc3 = xmlNewNode(NULL, BAD_CAST "LiteralOutput");1410 else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)1411 nc3 = xmlNewNode(NULL, BAD_CAST "ComplexOutput");1412 else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)1413 nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxOutput");1414 else1415 nc3 = xmlNewNode(NULL, BAD_CAST e->format);1416 }else{1417 if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0){1418 nc3 = xmlNewNode(NULL, BAD_CAST "LiteralData");1419 }1420 else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)1421 nc3 = xmlNewNode(NULL, BAD_CAST "ComplexData");1422 else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)1423 nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxData");1424 else1425 nc3 = xmlNewNode(NULL, BAD_CAST e->format);1426 }1427 1428 iotype* _tmp0=NULL;1429 iotype* _tmp=e->defaults;1430 int datatype=0;1431 bool hasUOM=false;1432 bool hasUOM1=false;1433 if(_tmp!=NULL){1434 if(strcmp(e->format,"LiteralOutput")==0 ||1435 strcmp(e->format,"LiteralData")==0){1436 datatype=1;1437 nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");1438 nc5 = xmlNewNode(NULL, BAD_CAST "Default");1439 }1440 else if(strcmp(e->format,"BoundingBoxOutput")==0 ||1441 strcmp(e->format,"BoundingBoxData")==0){1442 datatype=2;1443 nc5 = xmlNewNode(NULL, BAD_CAST "Default");1444 }1445 else{1446 nc4 = xmlNewNode(NULL, BAD_CAST "Default");1447 nc5 = xmlNewNode(NULL, BAD_CAST "Format");1448 }1449 1450 tmp1=_tmp->content;1451 1452 if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){1453 nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");1454 xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));1455 char tmp[1024];1456 sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);1457 xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);1458 xmlAddChild(nc3,nc8);1459 datatype=1;1460 }1461 1462 if(strncmp(type,"Input",5)==0){1463 1464 if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){1465 nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");1466 char *token,*saveptr1;1467 token=strtok_r(tmp1->value,",",&saveptr1);1468 while(token!=NULL){1469 nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");1470 char *tmps=strdup(token);1471 tmps[strlen(tmps)]=0;1472 xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));1473 free(tmps);1474 xmlAddChild(nc6,nc7);1475 token=strtok_r(NULL,",",&saveptr1);1476 }1477 if(getMap(_tmp->content,"range")!=NULL ||1478 getMap(_tmp->content,"rangeMin")!=NULL ||1479 getMap(_tmp->content,"rangeMax")!=NULL ||1480 getMap(_tmp->content,"rangeClosure")!=NULL )1481 goto doRange;1482 xmlAddChild(nc3,nc6);1483 isAnyValue=-1;1484 }1485 1486 tmp1=getMap(_tmp->content,"range");1487 if(tmp1==NULL)1488 tmp1=getMap(_tmp->content,"rangeMin");1489 if(tmp1==NULL)1490 tmp1=getMap(_tmp->content,"rangeMax");1491 1492 if(tmp1!=NULL && isAnyValue==1){1493 nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");1494 doRange:1495 1496 /**1497 * Range: Table 46 OGC Web Services Common Standard1498 */1499 nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");1500 1501 map* tmp0=getMap(tmp1,"range");1502 if(tmp0!=NULL){1503 char* pToken;1504 char* orig=zStrdup(tmp0->value);1505 /**1506 * RangeClosure: Table 47 OGC Web Services Common Standard1507 */1508 const char *tmp="closed";1509 if(orig[0]=='[' && orig[strlen(orig)-1]=='[')1510 tmp="closed-open";1511 else1512 if(orig[0]==']' && orig[strlen(orig)-1]==']')1513 tmp="open-closed";1514 else1515 if(orig[0]==']' && orig[strlen(orig)-1]=='[')1516 tmp="open";1517 xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);1518 pToken=strtok(orig,",");1519 int nci0=0;1520 while(pToken!=NULL){1521 char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));1522 if(nci0==0){1523 nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");1524 strncpy( tmpStr, pToken+1, strlen(pToken)-1 );1525 tmpStr[strlen(pToken)-1] = '\0';1526 }else{1527 nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");1528 const char* bkt;1529 if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){1530 strncpy( tmpStr, pToken, bkt - pToken );1531 tmpStr[bkt - pToken] = '\0';1532 }1533 }1534 xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));1535 free(tmpStr);1536 xmlAddChild(nc8,nc7);1537 nci0++;1538 pToken = strtok(NULL,",");1539 }1540 if(getMap(tmp1,"rangeSpacing")==NULL){1541 nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");1542 xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));1543 xmlAddChild(nc8,nc7);1544 }1545 free(orig);1546 }else{1547 1548 tmp0=getMap(tmp1,"rangeMin");1549 if(tmp0!=NULL){1550 nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");1551 xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));1552 xmlAddChild(nc8,nc7);1553 }else{1554 nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");1555 xmlAddChild(nc8,nc7);1556 }1557 tmp0=getMap(tmp1,"rangeMax");1558 if(tmp0!=NULL){1559 nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");1560 xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));1561 xmlAddChild(nc8,nc7);1562 }else{1563 nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");1564 xmlAddChild(nc8,nc7);1565 }1566 tmp0=getMap(tmp1,"rangeSpacing");1567 if(tmp0!=NULL){1568 nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");1569 xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));1570 xmlAddChild(nc8,nc7);1571 }1572 tmp0=getMap(tmp1,"rangeClosure");1573 if(tmp0!=NULL){1574 const char *tmp="closed";1575 if(strcasecmp(tmp0->value,"co")==0)1576 tmp="closed-open";1577 else1578 if(strcasecmp(tmp0->value,"oc")==0)1579 tmp="open-closed";1580 else1581 if(strcasecmp(tmp0->value,"o")==0)1582 tmp="open";1583 xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);1584 }else1585 xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");1586 }1587 if(_tmp0==NULL){1588 xmlAddChild(nc6,nc8);1589 _tmp0=e->supported;1590 if(_tmp0!=NULL &&1591 (getMap(_tmp0->content,"range")!=NULL ||1592 getMap(_tmp0->content,"rangeMin")!=NULL ||1593 getMap(_tmp0->content,"rangeMax")!=NULL ||1594 getMap(_tmp0->content,"rangeClosure")!=NULL )){1595 tmp1=_tmp0->content;1596 goto doRange;1597 }1598 }else{1599 _tmp0=_tmp0->next;1600 if(_tmp0!=NULL){1601 xmlAddChild(nc6,nc8);1602 if(getMap(_tmp0->content,"range")!=NULL ||1603 getMap(_tmp0->content,"rangeMin")!=NULL ||1604 getMap(_tmp0->content,"rangeMax")!=NULL ||1605 getMap(_tmp0->content,"rangeClosure")!=NULL ){1606 tmp1=_tmp0->content;1607 goto doRange;1608 }1609 }1610 }1611 xmlAddChild(nc6,nc8);1612 xmlAddChild(nc3,nc6);1613 isAnyValue=-1;1614 }1615 1616 }1617 1618 int oI=0;1619 for(oI=0;oI<13;oI++)1620 if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){1621 #ifdef DEBUG1622 printf("DATATYPE DEFAULT ? %s\n",tmp1->name);1623 #endif1624 if(strcmp(tmp1->name,"asReference")!=0 &&1625 strncasecmp(tmp1->name,"DataType",8)!=0 &&1626 strcasecmp(tmp1->name,"extension")!=0 &&1627 strcasecmp(tmp1->name,"value")!=0 &&1628 strcasecmp(tmp1->name,"AllowedValues")!=0 &&1629 strncasecmp(tmp1->name,"range",5)!=0){1630 if(datatype!=1){1631 char *tmp2=zCapitalize1(tmp1->name);1632 nc9 = xmlNewNode(NULL, BAD_CAST tmp2);1633 free(tmp2);1634 }1635 else{1636 char *tmp2=zCapitalize(tmp1->name);1637 nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);1638 free(tmp2);1639 }1640 xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));1641 xmlAddChild(nc5,nc9);1642 if(strcasecmp(tmp1->name,"uom")==0)1643 hasUOM1=true;1644 hasUOM=true;1645 }else1646 1647 tmp1=tmp1->next;1648 }1649 1650 1651 if(datatype!=2){1652 if(hasUOM==true){1653 xmlAddChild(nc4,nc5);1654 xmlAddChild(nc3,nc4);1655 }else{1656 if(hasUOM1==false){1657 xmlFreeNode(nc5);1658 if(datatype==1)1659 xmlFreeNode(nc4);1660 }1661 }1662 }else{1663 xmlAddChild(nc3,nc5);1664 }1665 1666 if(datatype!=1 && default1<0){1667 xmlFreeNode(nc5);1668 if(datatype!=2)1669 xmlFreeNode(nc4);1670 }1671 1672 map* metadata=e->metadata;1673 xmlNodePtr n=NULL;1674 int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");1675 xmlNsPtr ns_xlink=usedNs[xlinkId];1676 1677 while(metadata!=NULL){1678 nc6=xmlNewNode(ns_ows, BAD_CAST "Metadata");1679 xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);1680 xmlAddChild(nc2,nc6);1681 metadata=metadata->next;1682 }1683 1684 }1685 1686 _tmp=e->supported;1687 if(_tmp==NULL && datatype!=1)1688 _tmp=e->defaults;1689 1690 int hasSupported=-1;1691 1692 while(_tmp!=NULL){1693 if(hasSupported<0){1694 if(datatype==0){1695 nc4 = xmlNewNode(NULL, BAD_CAST "Supported");1696 nc5 = xmlNewNode(NULL, BAD_CAST "Format");1697 }1698 else1699 nc5 = xmlNewNode(NULL, BAD_CAST "Supported");1700 hasSupported=0;1701 }else1702 if(datatype==0)1703 nc5 = xmlNewNode(NULL, BAD_CAST "Format");1704 tmp1=_tmp->content;1705 int oI=0;1706 for(oI=0;oI<6;oI++)1707 if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){1708 #ifdef DEBUG1709 printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);1710 #endif1711 if(strcmp(tmp1->name,"asReference")!=0 &&1712 strcmp(tmp1->name,"value")!=0 &&1713 strcmp(tmp1->name,"DataType")!=0 &&1714 strcasecmp(tmp1->name,"extension")!=0){1715 if(datatype!=1){1716 char *tmp2=zCapitalize1(tmp1->name);1717 nc6 = xmlNewNode(NULL, BAD_CAST tmp2);1718 free(tmp2);1719 }1720 else{1721 char *tmp2=zCapitalize(tmp1->name);1722 nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);1723 free(tmp2);1724 }1725 if(datatype==2){1726 char *tmpv,*tmps;1727 tmps=strtok_r(tmp1->value,",",&tmpv);1728 while(tmps){1729 xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));1730 tmps=strtok_r(NULL,",",&tmpv);1731 if(tmps){1732 char *tmp2=zCapitalize1(tmp1->name);1733 nc6 = xmlNewNode(NULL, BAD_CAST tmp2);1734 free(tmp2);1735 }1736 }1737 }1738 else{1739 xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));1740 }1741 xmlAddChild(nc5,nc6);1742 }1743 tmp1=tmp1->next;1744 }1745 if(hasSupported<=0){1746 if(datatype==0){1747 xmlAddChild(nc4,nc5);1748 xmlAddChild(nc3,nc4);1749 }else{1750 if(datatype!=1)1751 xmlAddChild(nc3,nc5);1752 }1753 hasSupported=1;1754 }1755 else1756 if(datatype==0){1757 xmlAddChild(nc4,nc5);1758 xmlAddChild(nc3,nc4);1759 }1760 else1761 if(datatype!=1)1762 xmlAddChild(nc3,nc5);1763 1764 _tmp=_tmp->next;1765 }1766 1767 if(hasSupported==0){1768 if(datatype==0)1769 xmlFreeNode(nc4);1770 xmlFreeNode(nc5);1771 }1772 1773 _tmp=e->defaults;1774 if(datatype==1 && hasUOM1==true){1775 xmlAddChild(nc4,nc5);1776 xmlAddChild(nc3,nc4);1777 }1778 1779 if(in>0 && datatype==1 &&1780 getMap(_tmp->content,"AllowedValues")==NULL &&1781 getMap(_tmp->content,"range")==NULL &&1782 getMap(_tmp->content,"rangeMin")==NULL &&1783 getMap(_tmp->content,"rangeMax")==NULL &&1784 getMap(_tmp->content,"rangeClosure")==NULL ){1785 tmp1=getMap(_tmp->content,"dataType");1786 if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){1787 nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");1788 nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");1789 xmlAddChild(nc7,xmlNewText(BAD_CAST "true"));1790 xmlAddChild(nc6,nc7);1791 nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");1792 xmlAddChild(nc7,xmlNewText(BAD_CAST "false"));1793 xmlAddChild(nc6,nc7);1794 xmlAddChild(nc3,nc6);1795 }1796 else1797 xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));1798 }1799 1800 if(_tmp!=NULL && (tmp1=getMap(_tmp->content,"value"))!=NULL){1801 nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");1802 xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));1803 xmlAddChild(nc3,nc7);1804 }1805 1806 xmlAddChild(nc2,nc3);1807 1808 xmlAddChild(nc1,nc2);1809 1810 e=e->next;1811 }1812 }1813 1814 /**1815 * Generate a wps:Execute XML document.1816 *1817 * @param m the conf maps containing the main.cfg settings1818 * @param request the map representing the HTTP request1819 * @param pid the process identifier linked to a service1820 * @param serv the serv structure created from the zcfg file1821 * @param service the service name1822 * @param status the status returned by the service1823 * @param inputs the inputs provided1824 * @param outputs the outputs generated by the service1825 */1826 void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){1827 xmlNsPtr ns,ns_ows,ns_xlink;1828 xmlNodePtr nr,n,nc,nc1=NULL,nc3;1829 xmlDocPtr doc;1830 time_t time1;1831 time(&time1);1832 nr=NULL;1833 doc = xmlNewDoc(BAD_CAST "1.0");1834 n = printWPSHeader(doc,m,"Execute","ExecuteResponse");1835 int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");1836 ns=usedNs[wpsId];1837 int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");1838 ns_ows=usedNs[owsId];1839 int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");1840 ns_xlink=usedNs[xlinkId];1841 1842 char tmp[256];1843 char url[1024];1844 char stored_path[1024];1845 memset(tmp,0,256);1846 memset(url,0,1024);1847 memset(stored_path,0,1024);1848 maps* tmp_maps=getMaps(m,"main");1849 if(tmp_maps!=NULL){1850 map* tmpm1=getMap(tmp_maps->content,"serverAddress");1851 /**1852 * Check if the ZOO Service GetStatus is available in the local directory.1853 * If yes, then it uses a reference to an URL which the client can access1854 * to get information on the status of a running Service (using the1855 * percentCompleted attribute).1856 * Else fallback to the initial method using the xml file to write in ...1857 */1858 char ntmp[1024];1859 #ifndef WIN321860 getcwd(ntmp,1024);1861 #else1862 _getcwd(ntmp,1024);1863 #endif1864 struct stat myFileInfo;1865 int statRes;1866 char file_path[1024];1867 sprintf(file_path,"%s/GetStatus.zcfg",ntmp);1868 statRes=stat(file_path,&myFileInfo);1869 if(statRes==0){1870 char currentSid[128];1871 map* tmpm=getMap(tmp_maps->content,"rewriteUrl");1872 map *tmp_lenv=NULL;1873 tmp_lenv=getMapFromMaps(m,"lenv","usid");1874 if(tmp_lenv==NULL)1875 sprintf(currentSid,"%i",pid);1876 else1877 sprintf(currentSid,"%s",tmp_lenv->value);1878 if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){1879 sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);1880 }else{1881 if(strlen(tmpm->value)>0)1882 if(strcasecmp(tmpm->value,"true")!=0)1883 sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);1884 else1885 sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);1886 else1887 sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);1888 }1889 }else{1890 int lpid;1891 map* tmpm2=getMapFromMaps(m,"lenv","usid");1892 lpid=atoi(tmpm2->value);1893 tmpm2=getMap(tmp_maps->content,"tmpUrl");1894 if(tmpm1!=NULL && tmpm2!=NULL){1895 if( strncasecmp( tmpm2->value, "http://", 7) == 0 ||1896 strncasecmp( tmpm2->value, "https://", 8 ) == 0 ){1897 sprintf(url,"%s/%s_%i.xml",tmpm2->value,service,lpid);1898 }else1899 sprintf(url,"%s/%s/%s_%i.xml",tmpm1->value,tmpm2->value,service,lpid);1900 }1901 }1902 if(tmpm1!=NULL)1903 sprintf(tmp,"%s",tmpm1->value);1904 int lpid;1905 tmpm1=getMapFromMaps(m,"lenv","usid");1906 lpid=atoi(tmpm1->value);1907 tmpm1=getMapFromMaps(m,"main","TmpPath");1908 sprintf(stored_path,"%s/%s_%i.xml",tmpm1->value,service,lpid);1909 }1910 1911 1912 1913 xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);1914 map* test=getMap(request,"storeExecuteResponse");1915 bool hasStoredExecuteResponse=false;1916 if(test!=NULL && strcasecmp(test->value,"true")==0){1917 xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);1918 hasStoredExecuteResponse=true;1919 }1920 1921 nc = xmlNewNode(ns, BAD_CAST "Process");1922 map* tmp2=getMap(serv->content,"processVersion");1923 if(tmp2!=NULL)1924 xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);1925 1926 map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");1927 printDescription(nc,ns_ows,tmpI->value,serv->content);1928 1929 xmlAddChild(n,nc);1930 1931 nc = xmlNewNode(ns, BAD_CAST "Status");1932 const struct tm *tm;1933 size_t len;1934 time_t now;1935 char *tmp1;1936 map *tmpStatus;1937 1938 now = time ( NULL );1939 tm = localtime ( &now );1940 1941 tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));1942 1943 len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );1944 1945 xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);1946 1947 char sMsg[2048];1948 switch(status){1949 case SERVICE_SUCCEEDED:1950 nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");1951 sprintf(sMsg,_("The service \"%s\" ran successfully."),serv->name);1952 nc3=xmlNewText(BAD_CAST sMsg);1953 xmlAddChild(nc1,nc3);1954 break;1955 case SERVICE_STARTED:1956 nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");1957 tmpStatus=getMapFromMaps(m,"lenv","status");1958 xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);1959 sprintf(sMsg,_("The ZOO service \"%s\" is currently running. Please reload this document to get the up-to-date status of the service."),serv->name);1960 nc3=xmlNewText(BAD_CAST sMsg);1961 xmlAddChild(nc1,nc3);1962 break;1963 case SERVICE_ACCEPTED:1964 nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");1965 sprintf(sMsg,_("The service \"%s\" was accepted by the ZOO kernel and is running as a background task. Please access the URL in the statusLocation attribute provided in this document to get the up-to-date status and results."),serv->name);1966 nc3=xmlNewText(BAD_CAST sMsg);1967 xmlAddChild(nc1,nc3);1968 break;1969 case SERVICE_FAILED:1970 nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");1971 map *errorMap;1972 map *te;1973 te=getMapFromMaps(m,"lenv","code");1974 if(te!=NULL)1975 errorMap=createMap("code",te->value);1976 else1977 errorMap=createMap("code","NoApplicableCode");1978 te=getMapFromMaps(m,"lenv","message");1979 if(te!=NULL)1980 addToMap(errorMap,"text",_ss(te->value));1981 else1982 addToMap(errorMap,"text",_("No more information available"));1983 nc3=createExceptionReportNode(m,errorMap,0);1984 freeMap(&errorMap);1985 free(errorMap);1986 xmlAddChild(nc1,nc3);1987 break;1988 default :1989 printf(_("error code not know : %i\n"),status);1990 //exit(1);1991 break;1992 }1993 xmlAddChild(nc,nc1);1994 xmlAddChild(n,nc);1995 free(tmp1);1996 1997 #ifdef DEBUG1998 fprintf(stderr,"printProcessResponse 1 161\n");1999 #endif2000 2001 map* lineage=getMap(request,"lineage");2002 if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){2003 nc = xmlNewNode(ns, BAD_CAST "DataInputs");2004 maps* mcursor=inputs;2005 elements* scursor=NULL;2006 while(mcursor!=NULL /*&& scursor!=NULL*/){2007 scursor=getElements(serv->inputs,mcursor->name);2008 printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input");2009 mcursor=mcursor->next;2010 }2011 xmlAddChild(n,nc);2012 2013 #ifdef DEBUG2014 fprintf(stderr,"printProcessResponse 1 177\n");2015 #endif2016 2017 nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");2018 mcursor=outputs;2019 scursor=NULL;2020 while(mcursor!=NULL){2021 scursor=getElements(serv->outputs,mcursor->name);2022 printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");2023 mcursor=mcursor->next;2024 }2025 xmlAddChild(n,nc);2026 }2027 #ifdef DEBUG2028 fprintf(stderr,"printProcessResponse 1 190\n");2029 #endif2030 2031 /**2032 * Display the process output only when requested !2033 */2034 if(status==SERVICE_SUCCEEDED){2035 nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");2036 maps* mcursor=outputs;2037 elements* scursor=serv->outputs;2038 map* testResponse=getMap(request,"RawDataOutput");2039 if(testResponse==NULL)2040 testResponse=getMap(request,"ResponseDocument");2041 while(mcursor!=NULL){2042 map* tmp0=getMap(mcursor->content,"inRequest");2043 scursor=getElements(serv->outputs,mcursor->name);2044 if(scursor!=NULL){2045 if(testResponse==NULL || tmp0==NULL)2046 printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");2047 else2048 if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0)2049 printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");2050 }else2051 /**2052 * In case there was no definition found in the ZCFG file but2053 * present in the service code2054 */2055 printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");2056 mcursor=mcursor->next;2057 }2058 xmlAddChild(n,nc);2059 }2060 2061 if(hasStoredExecuteResponse==true && status!=SERVICE_STARTED){2062 semid lid=getShmLockId(m,1);2063 if(lid<0){2064 /* If the lock failed */2065 errorException(m,_("Lock failed."),"InternalError",NULL);2066 xmlFreeDoc(doc);2067 xmlCleanupParser();2068 zooXmlCleanupNs();2069 return;2070 }2071 else{2072 #ifdef DEBUG2073 fprintf(stderr,"LOCK %s %d !\n",__FILE__,__LINE__);2074 #endif2075 lockShm(lid);2076 /* We need to write the ExecuteResponse Document somewhere */2077 FILE* output=fopen(stored_path,"w");2078 if(output==NULL){2079 /* If the file cannot be created return an ExceptionReport */2080 char tmpMsg[1024];2081 sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path);2082 2083 errorException(m,tmpMsg,"InternalError",NULL);2084 xmlFreeDoc(doc);2085 xmlCleanupParser();2086 zooXmlCleanupNs();2087 unlockShm(lid);2088 return;2089 }2090 xmlChar *xmlbuff;2091 int buffersize;2092 xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);2093 fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);2094 xmlFree(xmlbuff);2095 fclose(output);2096 #ifdef DEBUG2097 fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);2098 #endif2099 unlockShm(lid);2100 map* test1=getMap(request,"status");2101 if(test1==NULL || strcasecmp(test1->value,"true")!=0){2102 removeShmLock(m,1);2103 }2104 }2105 }2106 printDocument(m,doc,pid);2107 2108 xmlCleanupParser();2109 zooXmlCleanupNs();2110 }2111 2112 /**2113 * Print a XML document.2114 *2115 * @param m the conf maps containing the main.cfg settings2116 * @param doc the XML document2117 * @param pid the process identifier linked to a service2118 */2119 void printDocument(maps* m, xmlDocPtr doc,int pid){2120 char *encoding=getEncoding(m);2121 if(pid==getpid()){2122 printHeaders(m);2123 printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);2124 }2125 fflush(stdout);2126 xmlChar *xmlbuff;2127 int buffersize;2128 /*2129 * Dump the document to a buffer and print it on stdout2130 * for demonstration purposes.2131 */2132 xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);2133 printf("%s",xmlbuff);2134 fflush(stdout);2135 /*2136 * Free associated memory.2137 */2138 xmlFree(xmlbuff);2139 xmlFreeDoc(doc);2140 xmlCleanupParser();2141 zooXmlCleanupNs();2142 }2143 2144 /**2145 * Print a XML document.2146 *2147 * @param doc the XML document (unused)2148 * @param nc the XML node to add the output definition2149 * @param ns_wps the wps XML namespace2150 * @param ns_ows the ows XML namespace2151 * @param e the output elements2152 * @param m the conf maps containing the main.cfg settings2153 * @param type the type (unused)2154 */2155 void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){2156 xmlNodePtr nc1;2157 nc1=xmlNewNode(ns_wps, BAD_CAST type);2158 map *tmp=NULL;2159 if(e!=NULL && e->defaults!=NULL)2160 tmp=e->defaults->content;2161 else{2162 /*2163 dumpElements(e);2164 */2165 return;2166 }2167 while(tmp!=NULL){2168 if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==02169 || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==02170 || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==02171 || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)2172 xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);2173 tmp=tmp->next;2174 }2175 tmp=getMap(e->defaults->content,"asReference");2176 if(tmp==NULL)2177 xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");2178 2179 tmp=e->content;2180 2181 printDescription(nc1,ns_ows,m->name,e->content);2182 2183 xmlAddChild(nc,nc1);2184 2185 }2186 2187 /**2188 * Generate XML nodes describing inputs or outputs metadata.2189 *2190 * @param doc the XML document2191 * @param nc the XML node to add the definition2192 * @param ns_wps the wps namespace2193 * @param ns_ows the ows namespace2194 * @param ns_xlink the xlink namespace2195 * @param e the output elements2196 * @param m the conf maps containing the main.cfg settings2197 * @param type the type2198 */2199 void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type){2200 2201 xmlNodePtr nc1,nc2,nc3;2202 nc1=xmlNewNode(ns_wps, BAD_CAST type);2203 map *tmp=NULL;2204 if(e!=NULL)2205 tmp=e->content;2206 else2207 tmp=m->content;2208 2209 nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");2210 if(e!=NULL)2211 nc3=xmlNewText(BAD_CAST e->name);2212 else2213 nc3=xmlNewText(BAD_CAST m->name);2214 2215 xmlAddChild(nc2,nc3);2216 xmlAddChild(nc1,nc2);2217 xmlAddChild(nc,nc1);2218 if(e!=NULL)2219 tmp=getMap(e->content,"Title");2220 else2221 tmp=getMap(m->content,"Title");2222 2223 if(tmp!=NULL){2224 nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);2225 nc3=xmlNewText(BAD_CAST _ss(tmp->value));2226 xmlAddChild(nc2,nc3);2227 xmlAddChild(nc1,nc2);2228 }2229 2230 if(e!=NULL)2231 tmp=getMap(e->content,"Abstract");2232 else2233 tmp=getMap(m->content,"Abstract");2234 2235 if(tmp!=NULL){2236 nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);2237 nc3=xmlNewText(BAD_CAST _ss(tmp->value));2238 xmlAddChild(nc2,nc3);2239 xmlAddChild(nc1,nc2);2240 xmlAddChild(nc,nc1);2241 }2242 2243 /**2244 * IO type Reference or full Data ?2245 */2246 map *tmpMap=getMap(m->content,"Reference");2247 if(tmpMap==NULL){2248 nc2=xmlNewNode(ns_wps, BAD_CAST "Data");2249 if(e!=NULL){2250 if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)2251 nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");2252 else2253 if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)2254 nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");2255 else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)2256 nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");2257 else2258 nc3=xmlNewNode(ns_wps, BAD_CAST e->format);2259 }2260 else {2261 map* tmpV=getMapFromMaps(m,"format","value");2262 if(tmpV!=NULL)2263 nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);2264 else2265 nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");2266 }2267 tmp=m->content;2268 2269 while(tmp!=NULL){2270 if(strcasecmp(tmp->name,"mimeType")==0 ||2271 strcasecmp(tmp->name,"encoding")==0 ||2272 strcasecmp(tmp->name,"schema")==0 ||2273 strcasecmp(tmp->name,"datatype")==0 ||2274 strcasecmp(tmp->name,"uom")==0) {2275 2276 xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);2277 }2278 tmp=tmp->next;2279 xmlAddChild(nc2,nc3);2280 }2281 if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {2282 map* bb=getMap(m->content,"value");2283 if(bb!=NULL) {2284 map* tmpRes=parseBoundingBox(bb->value);2285 printBoundingBox(ns_ows,nc3,tmpRes);2286 freeMap(&tmpRes);2287 free(tmpRes);2288 }2289 }2290 else {2291 if(e!=NULL)2292 tmp=getMap(e->defaults->content,"mimeType");2293 else2294 tmp=NULL;2295 2296 map* tmp1=getMap(m->content,"encoding");2297 map* tmp2=getMap(m->content,"mimeType");2298 map* tmp3=getMap(m->content,"value");2299 int hasValue=1;2300 if(tmp3==NULL){2301 tmp3=createMap("value","");2302 hasValue=-1;2303 }2304 2305 if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 ) // if encoding is base642306 || // or if2307 ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL // mime type is not text2308 && // nor2309 strstr(tmp2->value,"xml") == NULL // xml2310 && // nor2311 strstr(tmp2->value,"javascript") == NULL // javascript2312 &&2313 strstr(tmp2->value,"json") == NULL2314 &&2315 strstr(tmp2->value,"ecmascript") == NULL2316 &&2317 // include for backwards compatibility,2318 // although correct mime type is ...kml+xml:2319 strstr(tmp2->value,"google-earth.kml") == NULL )2320 )2321 ) { // then2322 map* rs=getMap(m->content,"size"); // obtain size2323 bool isSized=true;2324 if(rs==NULL){2325 char tmp1[1024];2326 sprintf(tmp1,"%ld",strlen(tmp3->value));2327 rs=createMap("size",tmp1);2328 isSized=false;2329 }2330 2331 xmlAddChild(nc3,xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value)))); // base 64 encode in XML2332 2333 if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {2334 xmlAttrPtr ap = xmlHasProp(nc3, BAD_CAST "encoding");2335 if (ap != NULL) {2336 xmlRemoveProp(ap);2337 }2338 xmlNewProp(nc3,BAD_CAST "encoding",BAD_CAST "base64");2339 }2340 2341 if(!isSized){2342 freeMap(&rs);2343 free(rs);2344 }2345 }2346 else if (tmp2!=NULL) { // else (text-based format)2347 if(strstr(tmp2->value, "javascript") != NULL || // if javascript put code in CDATA block2348 strstr(tmp2->value, "json") != NULL || // (will not be parsed by XML reader)2349 strstr(tmp2->value, "ecmascript") != NULL2350 ) {2351 xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));2352 }2353 else { // else2354 if (strstr(tmp2->value, "xml") != NULL || // if XML-based format2355 // include for backwards compatibility,2356 // although correct mime type is ...kml+xml:2357 strstr(tmp2->value, "google-earth.kml") != NULL2358 ) {2359 2360 int li=zooXmlAddDoc(tmp3->value);2361 xmlDocPtr doc = iDocs[li];2362 xmlNodePtr ir = xmlDocGetRootElement(doc);2363 xmlAddChild(nc3,ir);2364 }2365 else // else2366 xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value)); // add text node2367 }2368 xmlAddChild(nc2,nc3);2369 }2370 else {2371 xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));2372 }2373 2374 if(hasValue<0) {2375 freeMap(&tmp3);2376 free(tmp3);2377 }2378 }2379 }2380 else { // Reference2381 tmpMap=getMap(m->content,"Reference");2382 nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");2383 if(strcasecmp(type,"Output")==0)2384 xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);2385 else2386 xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);2387 2388 tmp=m->content;2389 while(tmp!=NULL) {2390 if(strcasecmp(tmp->name,"mimeType")==0 ||2391 strcasecmp(tmp->name,"encoding")==0 ||2392 strcasecmp(tmp->name,"schema")==0 ||2393 strcasecmp(tmp->name,"datatype")==0 ||2394 strcasecmp(tmp->name,"uom")==0){2395 2396 if(strcasecmp(tmp->name,"datatype")==0)2397 xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");2398 else2399 xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);2400 }2401 tmp=tmp->next;2402 xmlAddChild(nc2,nc3);2403 }2404 }2405 xmlAddChild(nc1,nc2);2406 xmlAddChild(nc,nc1);2407 }2408 2409 /**2410 * Create XML node with basic ows metadata informations (Identifier,Title,Abstract)2411 *2412 * @param root the root XML node to add the description2413 * @param ns_ows the ows XML namespace2414 * @param identifier the identifier to use2415 * @param amap the map containing the ows metadata informations2416 */2417 void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap){2418 xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");2419 2420 xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));2421 xmlAddChild(root,nc2);2422 map* tmp=amap;2423 const char *tmp2[2];2424 tmp2[0]="Title";2425 tmp2[1]="Abstract";2426 int j=0;2427 for(j=0;j<2;j++){2428 map* tmp1=getMap(tmp,tmp2[j]);2429 if(tmp1!=NULL){2430 nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);2431 xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));2432 xmlAddChild(root,nc2);2433 }2434 }2435 }2436 2437 /**2438 * Access the value of the encoding key in a maps2439 *2440 * @param m the maps to search for the encoding key2441 * @return the value of the encoding key in a maps if encoding key exists,2442 * "UTF-8" in other case.2443 */2444 char* getEncoding(maps* m){2445 if(m!=NULL){2446 map* tmp=getMap(m->content,"encoding");2447 if(tmp!=NULL){2448 return tmp->value;2449 }2450 else2451 return (char*)"UTF-8";2452 }2453 else2454 return (char*)"UTF-8";2455 }2456 2457 /**2458 * Access the value of the version key in a maps2459 *2460 * @param m the maps to search for the version key2461 * @return the value of the version key in a maps if encoding key exists,2462 * "1.0.0" in other case.2463 */2464 char* getVersion(maps* m){2465 if(m!=NULL){2466 map* tmp=getMap(m->content,"version");2467 if(tmp!=NULL){2468 return tmp->value;2469 }2470 else2471 return (char*)"1.0.0";2472 }2473 else2474 return (char*)"1.0.0";2475 }2476 2477 /**2478 * Print an OWS ExceptionReport Document and HTTP headers (when required)2479 * depending on the code.2480 * Set hasPrinted value to true in the [lenv] section.2481 *2482 * @param m the maps containing the settings of the main.cfg file2483 * @param s the map containing the text,code,locator keys2484 */2485 void printExceptionReportResponse(maps* m,map* s){2486 if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)2487 return;2488 int buffersize;2489 xmlDocPtr doc;2490 xmlChar *xmlbuff;2491 xmlNodePtr n;2492 2493 zooXmlCleanupNs();2494 doc = xmlNewDoc(BAD_CAST "1.0");2495 maps* tmpMap=getMaps(m,"main");2496 char *encoding=getEncoding(tmpMap);2497 const char *exceptionCode;2498 2499 map* tmp=getMap(s,"code");2500 if(tmp!=NULL){2501 if(strcmp(tmp->value,"OperationNotSupported")==0 ||2502 strcmp(tmp->value,"NoApplicableCode")==0)2503 exceptionCode="501 Not Implemented";2504 else2505 if(strcmp(tmp->value,"MissingParameterValue")==0 ||2506 strcmp(tmp->value,"InvalidUpdateSequence")==0 ||2507 strcmp(tmp->value,"OptionNotSupported")==0 ||2508 strcmp(tmp->value,"VersionNegotiationFailed")==0 ||2509 strcmp(tmp->value,"InvalidParameterValue")==0)2510 exceptionCode="400 Bad request";2511 else2512 exceptionCode="501 Internal Server Error";2513 }2514 else2515 exceptionCode="501 Internal Server Error";2516 2517 if(m!=NULL){2518 map *tmpSid=getMapFromMaps(m,"lenv","sid");2519 if(tmpSid!=NULL){2520 if( getpid()==atoi(tmpSid->value) ){2521 printHeaders(m);2522 printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);2523 }2524 }2525 else{2526 printHeaders(m);2527 printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);2528 }2529 }else{2530 printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);2531 }2532 n=createExceptionReportNode(m,s,1);2533 xmlDocSetRootElement(doc, n);2534 xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);2535 printf("%s",xmlbuff);2536 fflush(stdout);2537 xmlFreeDoc(doc);2538 xmlFree(xmlbuff);2539 xmlCleanupParser();2540 zooXmlCleanupNs();2541 if(m!=NULL)2542 setMapInMaps(m,"lenv","hasPrinted","true");2543 }2544 2545 /**2546 * Create an OWS ExceptionReport Node.2547 *2548 * @param m the conf maps2549 * @param s the map containing the text,code,locator keys2550 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or2551 * ows:ExceptionReport node respectively2552 * @return the ExceptionReport/ows:ExceptionReport node2553 */2554 xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){2555 2556 xmlNsPtr ns,ns_xsi;2557 xmlNodePtr n,nc,nc1;2558 2559 int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");2560 ns=usedNs[nsid];2561 if(use_ns==0){2562 ns=NULL;2563 }2564 n = xmlNewNode(ns, BAD_CAST "ExceptionReport");2565 if(use_ns==1){2566 xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST"ows");2567 int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");2568 ns_xsi=usedNs[xsiId];2569 xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd");2570 }2571 2572 2573 addLangAttr(n,m);2574 xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.1.0");2575 2576 int length=1;2577 int cnt=0;2578 map* len=getMap(s,"length");2579 if(len!=NULL)2580 length=atoi(len->value);2581 for(cnt=0;cnt<length;cnt++){2582 nc = xmlNewNode(ns, BAD_CAST "Exception");2583 2584 map* tmp=getMapArray(s,"code",cnt);2585 if(tmp==NULL)2586 tmp=getMap(s,"code");2587 if(tmp!=NULL)2588 xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);2589 else2590 xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");2591 2592 tmp=getMapArray(s,"locator",cnt);2593 if(tmp==NULL)2594 tmp=getMap(s,"locator");2595 if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)2596 xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);2597 2598 tmp=getMapArray(s,"text",cnt);2599 nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");2600 if(tmp!=NULL){2601 xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);2602 xmlAddChild(nc1,txt);2603 }2604 else{2605 xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));2606 }2607 xmlAddChild(nc,nc1);2608 xmlAddChild(n,nc);2609 }2610 return n;2611 }2612 2613 /**2614 * Print an OWS ExceptionReport.2615 *2616 * @param m the conf maps2617 * @param message the error message2618 * @param errorcode the error code2619 * @param locator the potential locator2620 */2621 int errorException(maps *m, const char *message, const char *errorcode, const char *locator)2622 {2623 map* errormap = createMap("text", message);2624 addToMap(errormap,"code", errorcode);2625 if(locator!=NULL)2626 addToMap(errormap,"locator", locator);2627 else2628 addToMap(errormap,"locator", "NULL");2629 printExceptionReportResponse(m,errormap);2630 freeMap(&errormap);2631 free(errormap);2632 return -1;2633 }2634 2635 /**2636 * Read a file generated by a service.2637 *2638 * @param m the conf maps2639 * @param content the output item2640 * @param filename the file to read2641 */2642 void readGeneratedFile(maps* m,map* content,char* filename){2643 FILE * file=fopen(filename,"rb");2644 if(file==NULL){2645 fprintf(stderr,"Failed to open file %s for reading purpose.\n",filename);2646 setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later");2647 return ;2648 }2649 fseek(file, 0, SEEK_END);2650 long count = ftell(file);2651 rewind(file);2652 struct stat file_status;2653 stat(filename, &file_status);2654 map* tmpMap1=getMap(content,"value");2655 if(tmpMap1==NULL){2656 addToMap(content,"value","");2657 tmpMap1=getMap(content,"value");2658 }2659 free(tmpMap1->value);2660 tmpMap1->value=(char*) malloc((count+1)*sizeof(char));2661 fread(tmpMap1->value,1,count,file);2662 tmpMap1->value[count]=0;2663 fclose(file);2664 char rsize[1000];2665 sprintf(rsize,"%ld",count);2666 addToMap(content,"size",rsize);2667 }2668 2669 /**2670 * Generate the output response (RawDataOutput or ResponseDocument)2671 *2672 * @param s the service structure containing the metadata informations2673 * @param request_inputs the inputs provided to the service for execution2674 * @param request_outputs the outputs updated by the service execution2675 * @param request_inputs1 the map containing the HTTP request2676 * @param cpid the process identifier attached to a service execution2677 * @param m the conf maps containing the main.cfg settings2678 * @param res the value returned by the service execution2679 */2680 void outputResponse(service* s,maps* request_inputs,maps* request_outputs,2681 map* request_inputs1,int cpid,maps* m,int res){2682 #ifdef DEBUG2683 dumpMaps(request_inputs);2684 dumpMaps(request_outputs);2685 fprintf(stderr,"printProcessResponse\n");2686 #endif2687 map* toto=getMap(request_inputs1,"RawDataOutput");2688 int asRaw=0;2689 if(toto!=NULL)2690 asRaw=1;2691 2692 maps* tmpSess=getMaps(m,"senv");2693 if(tmpSess!=NULL){2694 map *_tmp=getMapFromMaps(m,"lenv","cookie");2695 char* sessId=NULL;2696 if(_tmp!=NULL){2697 printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);2698 printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");2699 char session_file_path[100];2700 char *tmp1=strtok(_tmp->value,";");2701 if(tmp1!=NULL)2702 sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);2703 else2704 sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);2705 sessId=strdup(session_file_path);2706 }else{2707 maps* t=getMaps(m,"senv");2708 map*p=t->content;2709 while(p!=NULL){2710 if(strstr(p->name,"ID")!=NULL){2711 sessId=strdup(p->value);2712 break;2713 }2714 p=p->next;2715 }2716 }2717 char session_file_path[1024];2718 map *tmpPath=getMapFromMaps(m,"main","sessPath");2719 if(tmpPath==NULL)2720 tmpPath=getMapFromMaps(m,"main","tmpPath");2721 sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);2722 FILE* teste=fopen(session_file_path,"w");2723 if(teste==NULL){2724 char tmpMsg[1024];2725 sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);2726 errorException(m,tmpMsg,"InternalError",NULL);2727 2728 return;2729 }2730 else{2731 fclose(teste);2732 dumpMapsToFile(tmpSess,session_file_path);2733 }2734 }2735 2736 if(res==SERVICE_FAILED){2737 map *lenv;2738 lenv=getMapFromMaps(m,"lenv","message");2739 char *tmp0;2740 if(lenv!=NULL){2741 tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));2742 sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);2743 }2744 else{2745 tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));2746 sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));2747 }2748 errorException(m,tmp0,"InternalError",NULL);2749 free(tmp0);2750 return;2751 }2752 2753 2754 map *tmp1=getMapFromMaps(m,"main","tmpPath");2755 if(asRaw==0){2756 #ifdef DEBUG2757 fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");2758 dumpMaps(request_outputs);2759 #endif2760 maps* tmpI=request_outputs;2761 2762 while(tmpI!=NULL){2763 #ifdef USE_MS2764 map* testMap=getMap(tmpI->content,"useMapserver");2765 #endif2766 map *gfile=getMap(tmpI->content,"generated_file");2767 char *file_name;2768 if(gfile!=NULL){2769 gfile=getMap(tmpI->content,"expected_generated_file");2770 if(gfile==NULL){2771 gfile=getMap(tmpI->content,"generated_file");2772 }2773 readGeneratedFile(m,tmpI->content,gfile->value);2774 file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));2775 for(int i=0;i<strlen(gfile->value);i++)2776 file_name[i]=gfile->value[i+strlen(tmp1->value)];2777 }2778 2779 toto=getMap(tmpI->content,"asReference");2780 #ifdef USE_MS2781 if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)2782 #else2783 if(toto!=NULL && strcasecmp(toto->value,"true")==0)2784 #endif2785 {2786 elements* in=getElements(s->outputs,tmpI->name);2787 char *format=NULL;2788 if(in!=NULL){2789 format=strdup(in->format);2790 }else2791 format=strdup("LiteralData");2792 if(strcasecmp(format,"BoundingBoxData")==0){2793 addToMap(tmpI->content,"extension","xml");2794 addToMap(tmpI->content,"mimeType","text/xml");2795 addToMap(tmpI->content,"encoding","UTF-8");2796 addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");2797 }2798 2799 if(gfile==NULL){2800 map *ext=getMap(tmpI->content,"extension");2801 char *file_path;2802 char file_ext[32];2803 2804 if( ext != NULL && ext->value != NULL) {2805 strncpy(file_ext, ext->value, 32);2806 }2807 else {2808 // Obtain default file extension (see mimetypes.h).2809 // If the MIME type is not recognized, txt is used as the default extension2810 map* mtype=getMap(tmpI->content,"mimeType");2811 getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);2812 }2813 2814 file_name=(char*)malloc((strlen(s->name)+strlen(file_ext)+strlen(tmpI->name)+1024)*sizeof(char));2815 int cpid0=cpid+time(NULL);2816 sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,file_ext);2817 file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));2818 sprintf(file_path,"%s/%s",tmp1->value,file_name);2819 2820 FILE *ofile=fopen(file_path,"wb");2821 if(ofile==NULL){2822 char tmpMsg[1024];2823 sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name);2824 errorException(m,tmpMsg,"InternalError",NULL);2825 free(file_name);2826 free(file_path);2827 return;2828 }2829 free(file_path);2830 2831 toto=getMap(tmpI->content,"value");2832 if(strcasecmp(format,"BoundingBoxData")!=0){2833 map* size=getMap(tmpI->content,"size");2834 if(size!=NULL && toto!=NULL)2835 fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);2836 else2837 if(toto!=NULL && toto->value!=NULL)2838 fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);2839 }else{2840 printBoundingBoxDocument(m,tmpI,ofile);2841 }2842 fclose(ofile);2843 2844 }2845 map *tmp2=getMapFromMaps(m,"main","tmpUrl");2846 map *tmp3=getMapFromMaps(m,"main","serverAddress");2847 char *file_url;2848 if(strncasecmp(tmp2->value,"http://",7)==0 ||2849 strncasecmp(tmp2->value,"https://",8)==0){2850 file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));2851 sprintf(file_url,"%s/%s",tmp2->value,file_name);2852 }else{2853 file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));2854 sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);2855 }2856 addToMap(tmpI->content,"Reference",file_url);2857 free(format);2858 free(file_name);2859 free(file_url);2860 2861 }2862 #ifdef USE_MS2863 else{2864 if(testMap!=NULL){2865 setReferenceUrl(m,tmpI);2866 }2867 }2868 #endif2869 tmpI=tmpI->next;2870 }2871 map *r_inputs=getMap(s->content,"serviceProvider");2872 #ifdef DEBUG2873 fprintf(stderr,"SERVICE : %s\n",r_inputs->value);2874 dumpMaps(m);2875 #endif2876 printProcessResponse(m,request_inputs1,cpid,2877 // s,r_inputs->value,res,2878 s, s->name,res, // replace serviceProvider with serviceName in stored response file name2879 request_inputs,2880 request_outputs);2881 }2882 else{2883 /**2884 * We get the requested output or fallback to the first one if the2885 * requested one is not present in the resulting outputs maps.2886 */2887 maps* tmpI=NULL;2888 map* tmpIV=getMap(request_inputs1,"RawDataOutput");2889 if(tmpIV!=NULL){2890 tmpI=getMaps(request_outputs,tmpIV->value);2891 }2892 if(tmpI==NULL)2893 tmpI=request_outputs;2894 elements* e=getElements(s->outputs,tmpI->name);2895 if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){2896 printBoundingBoxDocument(m,tmpI,NULL);2897 }else{2898 map *gfile=getMap(tmpI->content,"generated_file");2899 if(gfile!=NULL){2900 gfile=getMap(tmpI->content,"expected_generated_file");2901 if(gfile==NULL){2902 gfile=getMap(tmpI->content,"generated_file");2903 }2904 readGeneratedFile(m,tmpI->content,gfile->value);2905 }2906 toto=getMap(tmpI->content,"value");2907 if(toto==NULL){2908 char tmpMsg[1024];2909 sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);2910 errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");2911 return;2912 }2913 map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");2914 if(fname!=NULL)2915 printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);2916 map* rs=getMapFromMaps(tmpI,tmpI->name,"size");2917 if(rs!=NULL)2918 printf("Content-Length: %s\r\n",rs->value);2919 printHeaders(m);2920 char mime[1024];2921 map* mi=getMap(tmpI->content,"mimeType");2922 #ifdef DEBUG2923 fprintf(stderr,"SERVICE OUTPUTS\n");2924 dumpMaps(request_outputs);2925 fprintf(stderr,"SERVICE OUTPUTS\n");2926 #endif2927 map* en=getMap(tmpI->content,"encoding");2928 if(mi!=NULL && en!=NULL)2929 sprintf(mime,2930 "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",2931 mi->value,en->value);2932 else2933 if(mi!=NULL)2934 sprintf(mime,2935 "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",2936 mi->value);2937 else2938 sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");2939 printf("%s",mime);2940 if(rs!=NULL)2941 fwrite(toto->value,1,atoi(rs->value),stdout);2942 else2943 fwrite(toto->value,1,strlen(toto->value),stdout);2944 #ifdef DEBUG2945 dumpMap(toto);2946 #endif2947 }2948 }2949 }2950 2951 /**2952 * Write a file from value and length2953 *2954 * @param fname the file name2955 * @param val the value2956 * @param length the value length2957 */2958 int writeFile(char* fname,char* val,int length){2959 FILE* of=fopen(fname,"wb");2960 if(of==NULL){2961 return -1;2962 }2963 size_t ret=fwrite(val,sizeof(char),length,of);2964 if(ret<length){2965 fprintf(stderr,"Write error occured!\n");2966 fclose(of);2967 return -1;2968 }2969 fclose(of);2970 return 1;2971 }2972 2973 /**2974 * Dump all values in a maps as files2975 *2976 * @param main_conf the maps containing the settings of the main.cfg file2977 * @param in the maps containing values to dump as files2978 */2979 void dumpMapsValuesToFiles(maps** main_conf,maps** in){2980 map* tmpPath=getMapFromMaps(*main_conf,"main","tmpPath");2981 map* tmpSid=getMapFromMaps(*main_conf,"lenv","sid");2982 maps* inputs=*in;2983 int length=0;2984 while(inputs!=NULL){2985 if(getMap(inputs->content,"mimeType")!=NULL &&2986 getMap(inputs->content,"cache_file")==NULL){2987 map* cMap=inputs->content;2988 if(getMap(cMap,"length")!=NULL){2989 map* tmpLength=getMap(cMap,"length");2990 int len=atoi(tmpLength->value);2991 int k=0;2992 for(k=0;k<len;k++){2993 map* cMimeType=getMapArray(cMap,"mimeType",k);2994 map* cValue=getMapArray(cMap,"value",k);2995 map* cSize=getMapArray(cMap,"size",k);2996 char file_ext[32];2997 getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32);2998 char* val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));2999 sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,k,file_ext);3000 length=0;3001 if(cSize!=NULL){3002 length=atoi(cSize->value);3003 }3004 writeFile(val,cValue->value,length);3005 setMapArray(cMap,"cache_file",k,val);3006 free(val);3007 }3008 }else{3009 int length=0;3010 map* cMimeType=getMap(cMap,"mimeType");3011 map* cValue=getMap(cMap,"value");3012 map* cSize=getMap(cMap,"size");3013 char file_ext[32];3014 getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32);3015 char *val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));3016 sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,0,file_ext);3017 if(cSize!=NULL){3018 length=atoi(cSize->value);3019 }3020 writeFile(val,cValue->value,length);3021 addToMap(cMap,"cache_file",val);3022 free(val);3023 }3024 }3025 inputs=inputs->next;3026 }3027 }3028 3029 /**3030 * Base64 encoding of a char*3031 *3032 * @param input the value to encode3033 * @param length the value length3034 * @return the buffer containing the base64 value3035 * @warning make sure to free the returned value3036 */3037 char *base64(const char *input, int length)3038 {3039 BIO *bmem, *b64;3040 BUF_MEM *bptr;3041 3042 b64 = BIO_new(BIO_f_base64());3043 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);3044 bmem = BIO_new(BIO_s_mem());3045 b64 = BIO_push(b64, bmem);3046 BIO_write(b64, input, length);3047 BIO_flush(b64);3048 BIO_get_mem_ptr(b64, &bptr);3049 3050 char *buff = (char *)malloc((bptr->length+1)*sizeof(char));3051 memcpy(buff, bptr->data, bptr->length);3052 buff[bptr->length] = 0;3053 3054 BIO_free_all(b64);3055 3056 return buff;3057 }3058 3059 /**3060 * Base64 decoding of a char*3061 *3062 * @param input the value to decode3063 * @param length the value length3064 * @param red the value length3065 * @return the buffer containing the base64 value3066 * @warning make sure to free the returned value3067 */3068 char *base64d(const char *input, int length,int* red)3069 {3070 BIO *b64, *bmem;3071 3072 char *buffer = (char *)malloc(length);3073 if(buffer){3074 memset(buffer, 0, length);3075 b64 = BIO_new(BIO_f_base64());3076 if(b64){3077 bmem = BIO_new_mem_buf((unsigned char*)input,length);3078 bmem = BIO_push(b64, bmem);3079 *red=BIO_read(bmem, buffer, length);3080 buffer[length-1]=0;3081 BIO_free_all(bmem);3082 }3083 }3084 return buffer;3085 }3086 3087 /**3088 * Read Base64 value and split it value by lines of 64 char.3089 *3090 * @param in the map containing the value to split3091 */3092 void readBase64(map **in){3093 char *res = NULL;3094 char *curs = (*in)->value;3095 int i = 0;3096 for (i = 0; i <= strlen ((*in)->value) / 64;3097 i++)3098 {3099 if (res == NULL)3100 res =3101 (char *) malloc (65 * sizeof (char));3102 else3103 res =3104 (char *) realloc (res,3105 (((i + 1) * 65) +3106 i) * sizeof (char));3107 int csize = i * 65;3108 strncpy (res + csize, curs, 64);3109 if (i == strlen ((*in)->value) / 64)3110 strcat (res, "\n\0");3111 else3112 {3113 strncpy (res + (((i + 1) * 64) + i),3114 "\n\0", 2);3115 curs += 64;3116 }3117 }3118 free ((*in)->value);3119 (*in)->value = zStrdup (res);3120 free (res);3121 }3122 3123 /**3124 * Make sure that each value encoded in base64 in a maps is decoded.3125 *3126 * @param in the maps containing the values3127 * @see readBase643128 */3129 void ensureDecodedBase64(maps **in){3130 maps* cursor=*in;3131 while(cursor!=NULL){3132 map *tmp=getMap(cursor->content,"encoding");3133 if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){3134 tmp=getMap(cursor->content,"value");3135 readBase64(&tmp);3136 addToMap(cursor->content,"base64_value",tmp->value);3137 int size=0;3138 char *s=strdup(tmp->value);3139 free(tmp->value);3140 tmp->value=base64d(s,strlen(s),&size);3141 free(s);3142 char sizes[1024];3143 sprintf(sizes,"%d",size);3144 addToMap(cursor->content,"size",sizes);3145 }3146 map* length=getMap(cursor->content,"length");3147 if(length!=NULL){3148 int len=atoi(length->value);3149 for(int i=1;i<len;i++){3150 tmp=getMapArray(cursor->content,"encoding",i);3151 if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){3152 char key[17];3153 sprintf(key,"base64_value_%d",i);3154 tmp=getMapArray(cursor->content,"value",i);3155 readBase64(&tmp);3156 addToMap(cursor->content,key,tmp->value);3157 int size=0;3158 char *s=strdup(tmp->value);3159 free(tmp->value);3160 tmp->value=base64d(s,strlen(s),&size);3161 free(s);3162 char sizes[1024];3163 sprintf(sizes,"%d",size);3164 sprintf(key,"size_%d",i);3165 addToMap(cursor->content,key,sizes);3166 }3167 }3168 }3169 cursor=cursor->next;3170 }3171 }3172 3173 /**3174 * Add the default values defined in the zcfg to a maps.3175 *3176 * @param out the maps containing the inputs or outputs given in the initial3177 * HTTP request3178 * @param in the description of all inputs or outputs available for a service3179 * @param m the maps containing the settings of the main.cfg file3180 * @param type 0 for inputs and 1 for outputs3181 * @param err the map to store potential missing mandatory input parameters or3182 * wrong output names depending on the type.3183 * @return "" if no error was detected, the name of last input or output causing3184 * an error.3185 */3186 char* addDefaultValues(maps** out,elements* in,maps* m,int type,map** err){3187 map *res=*err;3188 elements* tmpInputs=in;3189 maps* out1=*out;3190 char *result=NULL;3191 int nb=0;3192 if(type==1){3193 while(out1!=NULL){3194 if(getElements(in,out1->name)==NULL){3195 if(res==NULL){3196 res=createMap("value",out1->name);3197 }else{3198 setMapArray(res,"value",nb,out1->name);3199 }3200 nb++;3201 result=out1->name;3202 }3203 out1=out1->next;3204 }3205 if(res!=NULL){3206 *err=res;3207 return result;3208 }3209 out1=*out;3210 }3211 while(tmpInputs!=NULL){3212 maps *tmpMaps=getMaps(out1,tmpInputs->name);3213 if(tmpMaps==NULL){3214 maps* tmpMaps2=(maps*)malloc(MAPS_SIZE);3215 tmpMaps2->name=strdup(tmpInputs->name);3216 tmpMaps2->content=NULL;3217 tmpMaps2->next=NULL;3218 3219 if(type==0){3220 map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");3221 if(tmpMapMinO!=NULL){3222 if(atoi(tmpMapMinO->value)>=1){3223 freeMaps(&tmpMaps2);3224 free(tmpMaps2);3225 if(res==NULL){3226 res=createMap("value",tmpInputs->name);3227 }else{3228 setMapArray(res,"value",nb,tmpInputs->name);3229 }3230 nb++;3231 result=tmpInputs->name;3232 }3233 else{3234 if(tmpMaps2->content==NULL)3235 tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);3236 else3237 addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);3238 }3239 }3240 if(res==NULL){3241 map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");3242 if(tmpMaxO!=NULL){3243 if(tmpMaps2->content==NULL)3244 tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);3245 else3246 addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);3247 }3248 map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");3249 if(tmpMaxMB!=NULL){3250 if(tmpMaps2->content==NULL)3251 tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);3252 else3253 addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);3254 }3255 }3256 }3257 3258 if(res==NULL){3259 iotype* tmpIoType=tmpInputs->defaults;3260 if(tmpIoType!=NULL){3261 map* tmpm=tmpIoType->content;3262 while(tmpm!=NULL){3263 if(tmpMaps2->content==NULL)3264 tmpMaps2->content=createMap(tmpm->name,tmpm->value);3265 else3266 addToMap(tmpMaps2->content,tmpm->name,tmpm->value);3267 tmpm=tmpm->next;3268 }3269 }3270 addToMap(tmpMaps2->content,"inRequest","false");3271 if(type==0){3272 map *tmpMap=getMap(tmpMaps2->content,"value");3273 if(tmpMap==NULL)3274 addToMap(tmpMaps2->content,"value","NULL");3275 }3276 if(out1==NULL){3277 *out=dupMaps(&tmpMaps2);3278 out1=*out;3279 }3280 else3281 addMapsToMaps(&out1,tmpMaps2);3282 freeMap(&tmpMaps2->content);3283 free(tmpMaps2->content);3284 tmpMaps2->content=NULL;3285 freeMaps(&tmpMaps2);3286 free(tmpMaps2);3287 tmpMaps2=NULL;3288 }3289 }3290 else{3291 iotype* tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,3292 tmpMaps->content);3293 if(type==0) {3294 /**3295 * In case of an Input maps, then add the minOccurs and maxOccurs to the3296 * content map.3297 */3298 map* tmpMap1=getMap(tmpInputs->content,"minOccurs");3299 if(tmpMap1!=NULL){3300 if(tmpMaps->content==NULL)3301 tmpMaps->content=createMap("minOccurs",tmpMap1->value);3302 else3303 addToMap(tmpMaps->content,"minOccurs",tmpMap1->value);3304 }3305 map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");3306 if(tmpMaxO!=NULL){3307 if(tmpMaps->content==NULL)3308 tmpMaps->content=createMap("maxOccurs",tmpMaxO->value);3309 else3310 addToMap(tmpMaps->content,"maxOccurs",tmpMaxO->value);3311 }3312 map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");3313 if(tmpMaxMB!=NULL){3314 if(tmpMaps->content==NULL)3315 tmpMaps->content=createMap("maximumMegabytes",tmpMaxMB->value);3316 else3317 addToMap(tmpMaps->content,"maximumMegabytes",tmpMaxMB->value);3318 }3319 /**3320 * Parsing BoundingBoxData, fill the following map and then add it to3321 * the content map of the Input maps:3322 * lowerCorner, upperCorner, srs and dimensions3323 * cf. parseBoundingBox3324 */3325 if(tmpInputs->format!=NULL && strcasecmp(tmpInputs->format,"BoundingBoxData")==0){3326 maps* tmpI=getMaps(*out,tmpInputs->name);3327 if(tmpI!=NULL){3328 map* tmpV=getMap(tmpI->content,"value");3329 if(tmpV!=NULL){3330 char *tmpVS=strdup(tmpV->value);3331 map* tmp=parseBoundingBox(tmpVS);3332 free(tmpVS);3333 map* tmpC=tmp;3334 while(tmpC!=NULL){3335 addToMap(tmpMaps->content,tmpC->name,tmpC->value);3336 tmpC=tmpC->next;3337 }3338 freeMap(&tmp);3339 free(tmp);3340 }3341 }3342 }3343 }3344 3345 if(tmpIoType!=NULL){3346 map* tmpContent=tmpIoType->content;3347 map* cval=NULL;3348 int hasPassed=-1;3349 while(tmpContent!=NULL){3350 if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){3351 #ifdef DEBUG3352 fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);3353 #endif3354 if(tmpMaps->content==NULL)3355 tmpMaps->content=createMap(tmpContent->name,tmpContent->value);3356 else3357 addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);3358 3359 if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){3360 map* length=getMap(tmpMaps->content,"length");3361 int i;3362 char *tcn=strdup(tmpContent->name);3363 for(i=1;i<atoi(length->value);i++){3364 #ifdef DEBUG3365 dumpMap(tmpMaps->content);3366 fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);3367 #endif3368 int len=strlen((char*) tcn);3369 char *tmp1=(char *)malloc((len+10)*sizeof(char));3370 sprintf(tmp1,"%s_%d",tcn,i);3371 #ifdef DEBUG3372 fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);3373 #endif3374 addToMap(tmpMaps->content,tmp1,tmpContent->value);3375 free(tmp1);3376 hasPassed=1;3377 }3378 free(tcn);3379 }3380 }3381 tmpContent=tmpContent->next;3382 }3383 #ifdef USE_MS3384 /**3385 * check for useMapServer presence3386 */3387 map* tmpCheck=getMap(tmpIoType->content,"useMapServer");3388 if(tmpCheck!=NULL){3389 // Get the default value3390 tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);3391 tmpCheck=getMap(tmpMaps->content,"mimeType");3392 addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);3393 map* cursor=tmpIoType->content;3394 while(cursor!=NULL){3395 addToMap(tmpMaps->content,cursor->name,cursor->value);3396 cursor=cursor->next;3397 }3398 3399 cursor=tmpInputs->content;3400 while(cursor!=NULL){3401 if(strcasecmp(cursor->name,"Title")==0 ||3402 strcasecmp(cursor->name,"Abstract")==0)3403 addToMap(tmpMaps->content,cursor->name,cursor->value);3404 cursor=cursor->next;3405 }3406 }3407 #endif3408 }3409 if(tmpMaps->content==NULL)3410 tmpMaps->content=createMap("inRequest","true");3411 else3412 addToMap(tmpMaps->content,"inRequest","true");3413 3414 }3415 tmpInputs=tmpInputs->next;3416 }3417 if(res!=NULL){3418 *err=res;3419 return result;3420 }3421 return "";3422 }3423 3424 /**3425 * Parse a BoundingBox string3426 *3427 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):3428 * 10.2 Bounding box3429 *3430 *3431 * Value is provided as : lowerCorner,upperCorner,crs,dimension3432 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS843433 *3434 * A map to store boundingbox informations should contain:3435 * - lowerCorner : double,double (minimum within this bounding box)3436 * - upperCorner : double,double (maximum within this bounding box)3437 * - crs : URI (Reference to definition of the CRS)3438 * - dimensions : int3439 *3440 * Note : support only 2D bounding box.3441 *3442 * @param value the char* containing the KVP bouding box3443 * @return a map containing all the bounding box keys3444 */3445 map* parseBoundingBox(const char* value){3446 map *res=NULL;3447 if(value!=NULL){3448 char *cv,*cvp;3449 cv=strtok_r((char*) value,",",&cvp);3450 int cnt=0;3451 int icnt=0;3452 char *currentValue=NULL;3453 while(cv){3454 if(cnt<2)3455 if(currentValue!=NULL){3456 char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));3457 sprintf(finalValue,"%s%s",currentValue,cv);3458 switch(cnt){3459 case 0:3460 res=createMap("lowerCorner",finalValue);3461 break;3462 case 1:3463 addToMap(res,"upperCorner",finalValue);3464 icnt=-1;3465 break;3466 }3467 cnt++;3468 free(currentValue);3469 currentValue=NULL;3470 free(finalValue);3471 }3472 else{3473 currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));3474 sprintf(currentValue,"%s ",cv);3475 }3476 else3477 if(cnt==2){3478 addToMap(res,"crs",cv);3479 cnt++;3480 }3481 else3482 addToMap(res,"dimensions",cv);3483 icnt++;3484 cv=strtok_r(NULL,",",&cvp);3485 }3486 }3487 return res;3488 }3489 3490 /**3491 * Create required XML nodes for boundingbox and update the current XML node3492 *3493 * @param ns_ows the ows XML namespace3494 * @param n the XML node to update3495 * @param boundingbox the map containing the boundingbox definition3496 */3497 void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){3498 3499 xmlNodePtr lw=NULL,uc=NULL;3500 3501 map* tmp=getMap(boundingbox,"value");3502 3503 tmp=getMap(boundingbox,"lowerCorner");3504 if(tmp!=NULL){3505 lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");3506 xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));3507 }3508 3509 tmp=getMap(boundingbox,"upperCorner");3510 if(tmp!=NULL){3511 uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");3512 xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));3513 }3514 3515 tmp=getMap(boundingbox,"crs");3516 if(tmp!=NULL)3517 xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);3518 3519 tmp=getMap(boundingbox,"dimensions");3520 if(tmp!=NULL)3521 xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);3522 3523 xmlAddChild(n,lw);3524 xmlAddChild(n,uc);3525 3526 }3527 3528 /**3529 * Print an ows:BoundingBox XML document3530 *3531 * @param m the maps containing the settings of the main.cfg file3532 * @param boundingbox the maps containing the boundingbox definition3533 * @param file the file to print the BoundingBox (if NULL then print on stdout)3534 * @see parseBoundingBox, printBoundingBox3535 */3536 void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){3537 if(file==NULL)3538 rewind(stdout);3539 xmlNodePtr n;3540 xmlDocPtr doc;3541 xmlNsPtr ns_ows,ns_xsi;3542 xmlChar *xmlbuff;3543 int buffersize;3544 char *encoding=getEncoding(m);3545 map *tmp;3546 if(file==NULL){3547 int pid=0;3548 tmp=getMapFromMaps(m,"lenv","sid");3549 if(tmp!=NULL)3550 pid=atoi(tmp->value);3551 if(pid==getpid()){3552 printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);3553 }3554 fflush(stdout);3555 }3556 3557 doc = xmlNewDoc(BAD_CAST "1.0");3558 int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");3559 ns_ows=usedNs[owsId];3560 n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");3561 xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");3562 int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");3563 ns_xsi=usedNs[xsiId];3564 xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");3565 map *tmp1=getMap(boundingbox->content,"value");3566 tmp=parseBoundingBox(tmp1->value);3567 printBoundingBox(ns_ows,n,tmp);3568 xmlDocSetRootElement(doc, n);3569 3570 xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);3571 if(file==NULL)3572 printf("%s",xmlbuff);3573 else{3574 fprintf(file,"%s",xmlbuff);3575 }3576 3577 if(tmp!=NULL){3578 freeMap(&tmp);3579 free(tmp);3580 }3581 xmlFree(xmlbuff);3582 xmlFreeDoc(doc);3583 xmlCleanupParser();3584 zooXmlCleanupNs();3585 3586 }3587 3588 /**3589 * Compute md53590 *3591 * @param url the char*3592 * @return a char* representing the md5 of the url3593 * @warning make sure to free ressources returned by this function3594 */3595 char* getMd5(char* url){3596 EVP_MD_CTX md5ctx;3597 char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));3598 unsigned char result[EVP_MAX_MD_SIZE];3599 unsigned int len;3600 EVP_DigestInit(&md5ctx, EVP_md5());3601 EVP_DigestUpdate(&md5ctx, url, strlen(url));3602 EVP_DigestFinal_ex(&md5ctx,result,&len);3603 EVP_MD_CTX_cleanup(&md5ctx);3604 int i;3605 for(i = 0; i < len; i++){3606 if(i>0){3607 char *tmp=strdup(fresult);3608 sprintf(fresult,"%s%02x", tmp,result[i]);3609 free(tmp);3610 }3611 else3612 sprintf(fresult,"%02x",result[i]);3613 }3614 return fresult;3615 }3616 3617 /**3618 * Cache a file for a given request.3619 * For each cached file, the are two files stored, a .zca and a .zcm containing3620 * the downloaded content and the mimeType respectively.3621 *3622 * @param conf the maps containing the settings of the main.cfg file3623 * @param request the url used too fetch the content3624 * @param content the downloaded content3625 * @param mimeType the content mimeType3626 * @param length the content size3627 * @param filepath a buffer for storing the path of the cached file; may be NULL3628 * @param max_path the size of the allocated filepath buffer3629 */3630 void addToCache(maps* conf,char* request,char* content,char* mimeType,int length,3631 char* filepath, size_t max_path){3632 map* tmp=getMapFromMaps(conf,"main","cacheDir");3633 if(tmp!=NULL){3634 char* md5str=getMd5(request);3635 char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));3636 sprintf(fname,"%s/%s.zca",tmp->value,md5str);3637 #ifdef DEBUG3638 fprintf(stderr,"Cache list : %s\n",fname);3639 fflush(stderr);3640 #endif3641 FILE* fo=fopen(fname,"w+");3642 if(fo==NULL){3643 #ifdef DEBUG3644 fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));3645 #endif3646 filepath = NULL;3647 return;3648 }3649 fwrite(content,sizeof(char),length,fo);3650 fclose(fo);3651 3652 if (filepath != NULL) {3653 strncpy(filepath, fname, max_path);3654 }3655 3656 sprintf(fname,"%s/%s.zcm",tmp->value,md5str);3657 fo=fopen(fname,"w+");3658 #ifdef DEBUG3659 fprintf(stderr,"MIMETYPE: %s\n",mimeType);3660 #endif3661 fwrite(mimeType,sizeof(char),strlen(mimeType),fo);3662 fclose(fo);3663 3664 free(md5str);3665 free(fname);3666 }3667 else {3668 filepath = NULL;3669 }3670 }3671 3672 /**3673 * Verify if a url is available in the cache3674 *3675 * @param conf the maps containing the settings of the main.cfg file3676 * @param request the url3677 * @return the full name of the cached file if any, NULL in other case3678 * @warning make sure to free ressources returned by this function (if not NULL)3679 */3680 char* isInCache(maps* conf,char* request){3681 map* tmpM=getMapFromMaps(conf,"main","cacheDir");3682 if(tmpM!=NULL){3683 char* md5str=getMd5(request);3684 #ifdef DEBUG3685 fprintf(stderr,"MD5STR : (%s)\n\n",md5str);3686 #endif3687 char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));3688 sprintf(fname,"%s/%s.zca",tmpM->value,md5str);3689 struct stat f_status;3690 int s=stat(fname, &f_status);3691 if(s==0 && f_status.st_size>0){3692 free(md5str);3693 return fname;3694 }3695 free(md5str);3696 free(fname);3697 }3698 return NULL;3699 }3700 3701 /**3702 * Effectively run all the HTTP requests in the queue3703 *3704 * @param m the maps containing the settings of the main.cfg file3705 * @param inputs the maps containing the inputs (defined in the requests+added3706 * per default based on the zcfg file)3707 * @param hInternet the HINTERNET pointer3708 * @return 0 on success3709 */3710 int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet){3711 if(hInternet->nb>0){3712 processDownloads(hInternet);3713 maps* content=*inputs;3714 map* tmp1;3715 int index=0;3716 char sindex[5];3717 while(content!=NULL){3718 3719 map* length=getMap(content->content,"length");3720 int shouldClean=-1;3721 if(length==NULL){3722 length=createMap("length","1");3723 shouldClean=1;3724 }3725 for(int i=0;i<atoi(length->value);i++){3726 char* fcontent;3727 char *mimeType=NULL;3728 int fsize=0;3729 char cname[15];3730 char vname[11];3731 char vname1[11];3732 char sname[9];3733 char mname[15];3734 char icname[14];3735 char xname[16];3736 char oname[12];3737 if(index>0)3738 sprintf(vname1,"value_%d",index);3739 else3740 sprintf(vname1,"value");3741 3742 if(i>0){3743 tmp1=getMap(content->content,cname);3744 sprintf(cname,"cache_file_%d",i);3745 sprintf(vname,"value_%d",i);3746 sprintf(sname,"size_%d",i);3747 sprintf(mname,"mimeType_%d",i);3748 sprintf(icname,"isCached_%d",i);3749 sprintf(xname,"Reference_%d",i);3750 sprintf(oname,"Order_%d",i);3751 }else{3752 sprintf(cname,"cache_file");3753 sprintf(vname,"value");3754 sprintf(sname,"size");3755 sprintf(mname,"mimeType");3756 sprintf(icname,"isCached");3757 sprintf(xname,"Reference");3758 sprintf(oname,"Order");3759 }3760 3761 map* tmap=getMap(content->content,oname);3762 sprintf(sindex,"%d",index+1);3763 if((tmp1=getMap(content->content,xname))!=NULL && tmap!=NULL && strcasecmp(tmap->value,sindex)==0){3764 3765 if(getMap(content->content,icname)==NULL){3766 3767 fcontent=(char*)malloc((hInternet->ihandle[index].nDataLen+1)*sizeof(char));3768 if(fcontent == NULL){3769 return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);3770 }3771 size_t dwRead;3772 InternetReadFile(hInternet->ihandle[index],3773 (LPVOID)fcontent,3774 hInternet->ihandle[index].nDataLen,3775 &dwRead);3776 fcontent[hInternet->ihandle[index].nDataLen]=0;3777 fsize=hInternet->ihandle[index].nDataLen;3778 if(hInternet->ihandle[index].mimeType==NULL)3779 mimeType=strdup("none");3780 else3781 mimeType=strdup(hInternet->ihandle[index].mimeType);3782 3783 map* tmpMap=getMapOrFill(&content->content,vname,"");3784 free(tmpMap->value);3785 tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));3786 if(tmpMap->value==NULL){3787 return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);3788 }3789 memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));3790 3791 char ltmp1[256];3792 sprintf(ltmp1,"%d",fsize);3793 map* tmp=getMapFromMaps(*m,"main","cacheDir");3794 if(tmp!=NULL){3795 char* md5str=getMd5(tmp1->value);3796 char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));3797 sprintf(fname,"%s/%s.zca",tmp->value,md5str);3798 addToMap(content->content,cname,fname);3799 free(fname);3800 }3801 addToMap(content->content,sname,ltmp1);3802 addToMap(content->content,mname,mimeType);3803 addToCache(*m,tmp1->value,fcontent,mimeType,fsize, NULL, 0);3804 free(fcontent);3805 free(mimeType);3806 index++;3807 3808 }3809 }3810 }3811 if(shouldClean>0){3812 freeMap(&length);3813 free(length);3814 }3815 3816 content=content->next;3817 }3818 3819 }3820 return 0;3821 }3822 3823 /**3824 * Add a request in the download queue3825 *3826 * @param m the maps containing the settings of the main.cfg file3827 * @param url the url to add to the queue3828 */3829 void addRequestToQueue(maps** m,HINTERNET* hInternet,const char* url,bool req){3830 hInternet->waitingRequests[hInternet->nb]=strdup(url);3831 hInternet->ihandle[hInternet->nb].header=NULL;3832 if(req)3833 InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);3834 maps *oreq=getMaps(*m,"orequests");3835 if(oreq==NULL){3836 oreq=(maps*)malloc(MAPS_SIZE);3837 oreq->name=zStrdup("orequests");3838 oreq->content=createMap("value",url);3839 oreq->next=NULL;3840 addMapsToMaps(m,oreq);3841 freeMaps(&oreq);3842 free(oreq);3843 }else{3844 setMapArray(oreq->content,"value",hInternet->nb-1,url);3845 }3846 }3847 3848 /**3849 * Try to load file from cache or download a remote file if not in cache3850 *3851 * @param m the maps containing the settings of the main.cfg file3852 * @param content the map to update3853 * @param hInternet the HINTERNET pointer3854 * @param url the url to fetch3855 * @return 03856 */3857 int loadRemoteFile(maps** m,map** content,HINTERNET* hInternet,char *url){3858 char* fcontent;3859 char* cached=isInCache(*m,url);3860 char *mimeType=NULL;3861 int fsize=0;3862 3863 map* t=getMap(*content,"xlink:href");3864 if(t==NULL){3865 t=getMap((*content),"href");3866 addToMap(*content,"xlink:href",url);3867 }3868 3869 if(cached!=NULL){3870 3871 struct stat f_status;3872 int s=stat(cached, &f_status);3873 if(s==0){3874 fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));3875 FILE* f=fopen(cached,"rb");3876 fread(fcontent,f_status.st_size,1,f);3877 fsize=f_status.st_size;3878 fcontent[fsize]=0;3879 fclose(f);3880 addToMap(*content,"cache_file",cached);3881 }3882 cached[strlen(cached)-1]='m';3883 s=stat(cached, &f_status);3884 if(s==0){3885 mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));3886 FILE* f=fopen(cached,"rb");3887 fread(mimeType,f_status.st_size,1,f);3888 mimeType[f_status.st_size]=0;3889 fclose(f);3890 }3891 3892 }else{3893 addRequestToQueue(m,hInternet,url,true);3894 return 0;3895 }3896 if(fsize==0){3897 return errorException(*m, _("Unable to download the file."), "InternalError",NULL);3898 }3899 if(mimeType!=NULL){3900 addToMap(*content,"fmimeType",mimeType);3901 }3902 3903 map* tmpMap=getMapOrFill(content,"value","");3904 3905 free(tmpMap->value);3906 3907 tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));3908 if(tmpMap->value==NULL)3909 return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);3910 memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));3911 3912 char ltmp1[256];3913 sprintf(ltmp1,"%d",fsize);3914 addToMap(*content,"size",ltmp1);3915 if(cached==NULL){3916 addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);3917 }3918 else{3919 addToMap(*content,"isCached","true");3920 map* tmp=getMapFromMaps(*m,"main","cacheDir");3921 if(tmp!=NULL){3922 map *c=getMap((*content),"xlink:href");3923 char* md5str=getMd5(c->value);3924 char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));3925 sprintf(fname,"%s/%s.zca",tmp->value,md5str);3926 addToMap(*content,"cache_file",fname);3927 free(fname);3928 }3929 }3930 free(fcontent);3931 free(mimeType);3932 free(cached);3933 return 0;3934 }3935 3936 /**3937 * Read a file using the GDAL VSI API3938 *3939 * @param conf the maps containing the settings of the main.cfg file3940 * @param dataSource the datasource name to read3941 * @warning make sure to free ressources returned by this function3942 */3943 char *readVSIFile(maps* conf,const char* dataSource){3944 VSILFILE * fichier=VSIFOpenL(dataSource,"rb");3945 VSIStatBufL file_status;3946 VSIStatL(dataSource, &file_status);3947 if(fichier==NULL){3948 char tmp[1024];3949 sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",3950 dataSource,file_status.st_size);3951 setMapInMaps(conf,"lenv","message",tmp);3952 return NULL;3953 }3954 char *res1=(char *)malloc(file_status.st_size*sizeof(char));3955 VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);3956 res1[file_status.st_size-1]=0;3957 VSIFCloseL(fichier);3958 VSIUnlink(dataSource);3959 return res1;3960 }3961 3962 /**3963 * Extract the service identifier from the full service identifier3964 * ie:3965 * - Full service name: OTB.BandMath3966 * - Service name: BandMath3967 *3968 * @param conf the maps containing the settings of the main.cfg file3969 * @param conf_dir the full path to the ZOO-Kernel directory3970 * @param identifier the full service name (potentialy including a prefix, ie:3971 * Prefix.MyService)3972 * @param buffer the resulting service identifier (without any prefix)3973 */3974 void parseIdentifier(maps* conf,char* conf_dir,char *identifier,char* buffer){3975 setMapInMaps(conf,"lenv","oIdentifier",identifier);3976 char *lid=zStrdup(identifier);3977 char *saveptr1;3978 char *tmps1=strtok_r(lid,".",&saveptr1);3979 int level=0;3980 char key[25];3981 char levels[18];3982 while(tmps1!=NULL){3983 char *test=zStrdup(tmps1);3984 char* tmps2=(char*)malloc((strlen(test)+2)*sizeof(char));3985 sprintf(key,"sprefix_%d",level);3986 sprintf(tmps2,"%s.",test);3987 sprintf(levels,"%d",level);3988 setMapInMaps(conf,"lenv","level",levels);3989 setMapInMaps(conf,"lenv",key,tmps2);3990 free(tmps2);3991 free(test);3992 level++;3993 tmps1=strtok_r(NULL,".",&saveptr1);3994 }3995 int i=0;3996 sprintf(buffer,"%s",conf_dir);3997 for(i=0;i<level;i++){3998 char *tmp0=zStrdup(buffer);3999 sprintf(key,"sprefix_%d",i);4000 map* tmp00=getMapFromMaps(conf,"lenv",key);4001 if(tmp00!=NULL)4002 sprintf(buffer,"%s/%s",tmp0,tmp00->value);4003 free(tmp0);4004 buffer[strlen(buffer)-1]=0;4005 if(i+1<level){4006 #ifdef IGNORE_METAPATH4007 map* tmpMap = createMap("metapath", "");4008 #else4009 map* tmpMap=getMapFromMaps(conf,"lenv","metapath");4010 #endif4011 if(tmpMap==NULL || strlen(tmpMap->value)==0){4012 char *tmp01=zStrdup(tmp00->value);4013 tmp01[strlen(tmp01)-1]=0;4014 setMapInMaps(conf,"lenv","metapath",tmp01);4015 free(tmp01);4016 tmp01=NULL;4017 }4018 else{4019 if(tmp00!=NULL && tmpMap!=NULL){4020 char *tmp00s=zStrdup(tmp00->value);4021 tmp00s[strlen(tmp00s)-1]=0;4022 char *value=(char*)malloc((strlen(tmp00s)+strlen(tmpMap->value)+2)*sizeof(char));4023 sprintf(value,"%s/%s",tmpMap->value,tmp00s);4024 setMapInMaps(conf,"lenv","metapath",value);4025 free(value);4026 free(tmp00s);4027 value=NULL;4028 }4029 }4030 }else{4031 char *tmp01=zStrdup(tmp00->value);4032 tmp01[strlen(tmp01)-1]=0;4033 setMapInMaps(conf,"lenv","Identifier",tmp01);4034 free(tmp01);4035 }4036 }4037 char *tmp0=zStrdup(buffer);4038 sprintf(buffer,"%s.zcfg",tmp0);4039 free(tmp0);4040 free(lid);4041 }4042 4043 566 /** 4044 567 * Update the status of an ongoing service … … 4111 634 } 4112 635 4113 /**4114 * Verify if a parameter value is valid.4115 *4116 * @param request the request map4117 * @param res the error map potentially generated4118 * @param toCheck the parameter to use4119 * @param avalues the acceptable values (or null if testing only for presence)4120 * @param mandatory verify the presence of the parameter if mandatory > 04121 */4122 void checkValidValue(map* request,map** res,const char* toCheck,const char** avalues,int mandatory){4123 map* lres=*res;4124 map* r_inputs = getMap (request,toCheck);4125 if (r_inputs == NULL){4126 if(mandatory>0){4127 char *replace=_("Mandatory parameter <%s> was not specified");4128 char *message=(char*)malloc((strlen(replace)+strlen(toCheck)+1)*sizeof(char));4129 sprintf(message,replace,toCheck);4130 if(lres==NULL){4131 lres=createMap("code","MissingParameterValue");4132 addToMap(lres,"text",message);4133 addToMap(lres,"locator",toCheck);4134 }else{4135 int length=1;4136 map* len=getMap(lres,"length");4137 if(len!=NULL){4138 length=atoi(len->value);4139 }4140 setMapArray(lres,"text",length,message);4141 setMapArray(lres,"locator",length,toCheck);4142 setMapArray(lres,"code",length,"MissingParameter");4143 }4144 free(message);4145 }4146 }else{4147 if(avalues==NULL)4148 return;4149 int nb=0;4150 int hasValidValue=-1;4151 while(avalues[nb]!=NULL){4152 if(strcasecmp(avalues[nb],r_inputs->value)==0){4153 hasValidValue=1;4154 break;4155 }4156 nb++;4157 }4158 if(hasValidValue<0){4159 char *replace=_("The value <%s> was not recognized, %s %s the only acceptable value.");4160 nb=0;4161 char *vvalues=NULL;4162 char* num=_("is");4163 while(avalues[nb]!=NULL){4164 char *tvalues;4165 if(vvalues==NULL){4166 vvalues=(char*)malloc((strlen(avalues[nb])+3)*sizeof(char));4167 sprintf(vvalues,"%s",avalues[nb]);4168 }4169 else{4170 tvalues=zStrdup(vvalues);4171 vvalues=(char*)realloc(vvalues,(strlen(tvalues)+strlen(avalues[nb])+3)*sizeof(char));4172 sprintf(vvalues,"%s, %s",tvalues,avalues[nb]);4173 free(tvalues);4174 num=_("are");4175 }4176 nb++;4177 }4178 char *message=(char*)malloc((strlen(replace)+strlen(num)+strlen(vvalues)+strlen(toCheck)+1)*sizeof(char));4179 sprintf(message,replace,toCheck,vvalues,num);4180 if(lres==NULL){4181 lres=createMap("code","InvalidParameterValue");4182 addToMap(lres,"text",message);4183 addToMap(lres,"locator",toCheck);4184 }else{4185 int length=1;4186 map* len=getMap(lres,"length");4187 if(len!=NULL){4188 length=atoi(len->value);4189 }4190 setMapArray(lres,"text",length,message);4191 setMapArray(lres,"locator",length,toCheck);4192 setMapArray(lres,"code",length,"InvalidParameterValue");4193 }4194 }4195 }4196 if(lres!=NULL){4197 *res=lres;4198 }4199 }4200 4201 /**4202 * Access the last error message returned by the OS when trying to dynamically4203 * load a shared library.4204 *4205 * @return the last error message4206 * @warning The character string returned from getLastErrorMessage resides4207 * in a static buffer. The application should not write to this4208 * buffer or attempt to free() it.4209 */4210 char* getLastErrorMessage() {4211 #ifdef WIN324212 LPVOID lpMsgBuf;4213 DWORD errCode = GetLastError();4214 static char msg[ERROR_MSG_MAX_LENGTH];4215 size_t i;4216 4217 DWORD length = FormatMessage(4218 FORMAT_MESSAGE_ALLOCATE_BUFFER |4219 FORMAT_MESSAGE_FROM_SYSTEM |4220 FORMAT_MESSAGE_IGNORE_INSERTS,4221 NULL,4222 errCode,4223 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),4224 (LPTSTR) &lpMsgBuf,4225 0, NULL );4226 4227 #ifdef UNICODE4228 wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,4229 (wchar_t*) lpMsgBuf, _TRUNCATE );4230 #else4231 strcpy_s( msg, ERROR_MSG_MAX_LENGTH,4232 (char *) lpMsgBuf );4233 #endif4234 LocalFree(lpMsgBuf);4235 4236 return msg;4237 #else4238 return dlerror();4239 #endif4240 }4241
Note: See TracChangeset
for help on using the changeset viewer.