#include "fitsio2.h"
#include "group.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(WIN32) || defined(__WIN32__)
#include <direct.h>
#endif
#if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#define HEX_ESCAPE '%'
int ffgtcr(fitsfile *fptr,
char *grpname,
int grouptype,
int *status )
{
int hdutype;
int hdunum;
if(*status != 0) return(*status);
*status = fits_get_num_hdus(fptr,&hdunum,status);
if (0 != hdunum) {
*status = fits_movabs_hdu(fptr,hdunum,&hdutype,status);
}
if (0 != *status ) *status = 0;
*status = fits_insert_group(fptr,grpname,grouptype,status);
return(*status);
}
int ffgtis(fitsfile *fptr,
char *grpname,
int grouptype,
int *status)
{
int tfields = 0;
int hdunum = 0;
int hdutype = 0;
int extver;
int i;
long pcount = 0;
char *ttype[6];
char *tform[6];
char ttypeBuff[102];
char tformBuff[54];
char extname[] = "GROUPING";
char keyword[FLEN_KEYWORD];
char keyvalue[FLEN_VALUE];
char comment[FLEN_COMMENT];
do
{
for(i = 0; i < 6; ++i)
{
ttype[i] = ttypeBuff+(i*17);
tform[i] = tformBuff+(i*9);
}
*status = ffgtdc(grouptype,0,0,0,0,0,0,ttype,tform,&tfields,status);
*status = fits_insert_btbl(fptr,0,tfields,ttype,tform,NULL,
NULL,pcount,status);
if(*status != 0) continue;
fits_get_hdu_num(fptr,&hdunum);
fits_read_keyword(fptr,"TFIELDS",keyvalue,comment,status);
fits_insert_key_str(fptr,"EXTNAME",extname,
"HDU contains a Grouping Table",status);
fits_insert_key_lng(fptr,"EXTVER",0,"Grouping Table vers. (this file)",
status);
if(grpname != NULL && strlen(grpname) > 0)
fits_insert_key_str(fptr,"GRPNAME",grpname,"Grouping Table name",
status);
for(i = 0; i < tfields && *status == 0; ++i)
{
if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
fits_strcasecmp(ttype[i],"MEMBER_VERSION") == 0)
{
snprintf(keyword,FLEN_KEYWORD,"TFORM%d",i+1);
*status = fits_read_key_str(fptr,keyword,keyvalue,comment,
status);
snprintf(keyword,FLEN_KEYWORD,"TNULL%d",i+1);
*status = fits_insert_key_lng(fptr,keyword,0,"Column Null Value",
status);
}
}
for(extver = 1;
(fits_movnam_hdu(fptr,ANY_HDU,"GROUPING",extver,status)) == 0;
++extver);
if(*status == BAD_HDU_NUM) *status = 0;
fits_movabs_hdu(fptr,hdunum,&hdutype,status);
fits_modify_key_lng(fptr,"EXTVER",extver,"&",status);
}while(0);
return(*status);
}
int ffgtch(fitsfile *gfptr,
int grouptype,
int *status)
{
int xtensionCol, extnameCol, extverCol, positionCol, locationCol, uriCol;
int ncols = 0;
int colnum = 0;
int nrows = 0;
int grptype = 0;
int i,j;
long intNull = 0;
long tfields = 0;
char *tform[6];
char *ttype[6];
unsigned char charNull[1] = {'\0'};
char ttypeBuff[102];
char tformBuff[54];
char keyword[FLEN_KEYWORD];
char keyvalue[FLEN_VALUE];
char comment[FLEN_COMMENT];
if(*status != 0) return(*status);
do
{
for(i = 0; i < 6; ++i)
{
ttype[i] = ttypeBuff+(i*17);
tform[i] = tformBuff+(i*9);
}
*status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
&locationCol,&uriCol,&grptype,status);
if(*status != 0) continue;
*status = fits_read_key_lng(gfptr,"TFIELDS",&tfields,comment,status);
*status = ffgtdc(grouptype,xtensionCol,extnameCol,extverCol,positionCol,
locationCol,uriCol,ttype,tform,&ncols,status);
switch(grouptype)
{
case GT_ID_ALL_URI:
break;
case GT_ID_REF:
if(positionCol != 0)
{
*status = fits_delete_col(gfptr,positionCol,status);
--tfields;
if(uriCol > positionCol) --uriCol;
if(locationCol > positionCol) --locationCol;
}
if(uriCol != 0)
{
*status = fits_delete_col(gfptr,uriCol,status);
--tfields;
if(locationCol > uriCol) --locationCol;
}
if(locationCol != 0)
*status = fits_delete_col(gfptr,locationCol,status);
break;
case GT_ID_POS:
if(xtensionCol != 0)
{
*status = fits_delete_col(gfptr,xtensionCol,status);
--tfields;
if(extnameCol > xtensionCol) --extnameCol;
if(extverCol > xtensionCol) --extverCol;
if(uriCol > xtensionCol) --uriCol;
if(locationCol > xtensionCol) --locationCol;
}
if(extnameCol != 0)
{
*status = fits_delete_col(gfptr,extnameCol,status);
--tfields;
if(extverCol > extnameCol) --extverCol;
if(uriCol > extnameCol) --uriCol;
if(locationCol > extnameCol) --locationCol;
}
if(extverCol != 0)
{
*status = fits_delete_col(gfptr,extverCol,status);
--tfields;
if(uriCol > extverCol) --uriCol;
if(locationCol > extverCol) --locationCol;
}
if(uriCol != 0)
{
*status = fits_delete_col(gfptr,uriCol,status);
--tfields;
if(locationCol > uriCol) --locationCol;
}
if(locationCol != 0)
{
*status = fits_delete_col(gfptr,locationCol,status);
--tfields;
}
break;
case GT_ID_ALL:
if(uriCol != 0)
{
*status = fits_delete_col(gfptr,uriCol,status);
--tfields;
if(locationCol > uriCol) --locationCol;
}
if(locationCol != 0)
{
*status = fits_delete_col(gfptr,locationCol,status);
--tfields;
}
break;
case GT_ID_REF_URI:
if(positionCol != 0)
{
*status = fits_delete_col(gfptr,positionCol,status);
--tfields;
}
break;
case GT_ID_POS_URI:
if(xtensionCol != 0)
{
*status = fits_delete_col(gfptr,xtensionCol,status);
--tfields;
if(extnameCol > xtensionCol) --extnameCol;
if(extverCol > xtensionCol) --extverCol;
}
if(extnameCol != 0)
{
*status = fits_delete_col(gfptr,extnameCol,status);
--tfields;
if(extverCol > extnameCol) --extverCol;
}
if(extverCol != 0)
{
*status = fits_delete_col(gfptr,extverCol,status);
--tfields;
}
break;
default:
*status = BAD_OPTION;
ffpmsg("Invalid value for grouptype parameter specified (ffgtch)");
break;
}
for(i = 0; i < ncols && *status == 0; ++i)
*status = fits_insert_col(gfptr,tfields+i+1,ttype[i],tform[i],status);
for(i = 0; i < ncols && *status == 0; ++i)
{
if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
fits_strcasecmp(ttype[i],"MEMBER_VERSION") == 0)
{
*status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum,
status);
snprintf(keyword,FLEN_KEYWORD,"TFORM%d",colnum);
*status = fits_read_key_str(gfptr,keyword,keyvalue,comment,
status);
snprintf(keyword,FLEN_KEYWORD,"TNULL%d",colnum);
*status = fits_insert_key_lng(gfptr,keyword,0,
"Column Null Value",status);
for(j = 1; j <= nrows && *status == 0; ++j)
*status = fits_write_col_lng(gfptr,colnum,j,1,1,&intNull,
status);
}
else if(fits_strcasecmp(ttype[i],"MEMBER_XTENSION") == 0 ||
fits_strcasecmp(ttype[i],"MEMBER_NAME") == 0 ||
fits_strcasecmp(ttype[i],"MEMBER_URI_TYPE") == 0 ||
fits_strcasecmp(ttype[i],"MEMBER_LOCATION") == 0)
{
*status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum,
status);
for(j = 1; j <= nrows && *status == 0; ++j)
*status = fits_write_col_byt(gfptr,colnum,j,1,1,charNull,
status);
}
}
}while(0);
return(*status);
}
int ffgtrm(fitsfile *gfptr,
int rmopt,
int *status)
{
int hdutype;
long i;
long nmembers = 0;
HDUtracker HDU;
if(*status != 0) return(*status);
switch(rmopt)
{
case OPT_RM_GPT:
*status = fits_get_num_members(gfptr,&nmembers,status);
for(i = nmembers; i > 0 && *status == 0; --i)
*status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status);
break;
case OPT_RM_ALL:
HDU.nHDU = 0;
*status = fftsad(gfptr,&HDU,NULL,NULL);
*status = ffgtrmr(gfptr,&HDU,status);
for(i = 0; i < HDU.nHDU; ++i)
{
free(HDU.filename[i]);
free(HDU.newFilename[i]);
}
break;
default:
*status = BAD_OPTION;
ffpmsg("Invalid value for the rmopt parameter specified (ffgtrm)");
break;
}
*status = ffgmul(gfptr,0,status);
*status = fits_delete_hdu(gfptr,&hdutype,status);
return(*status);
}
int ffgtcp(fitsfile *infptr,
fitsfile *outfptr,
int cpopt,
int *status)
{
int i;
HDUtracker HDU;
if(*status != 0) return(*status);
if(infptr == outfptr) *status = IDENTICAL_POINTERS;
else
{
HDU.nHDU = 0;
*status = fftsad(infptr,&HDU,NULL,NULL);
*status = ffgtcpr(infptr,outfptr,cpopt,&HDU,status);
for(i = 0; i < HDU.nHDU; ++i)
{
free(HDU.filename[i]);
free(HDU.newFilename[i]);
}
}
return(*status);
}
int ffgtmg(fitsfile *infptr,
fitsfile *outfptr,
int mgopt,
int *status)
{
long i ;
long nmembers = 0;
fitsfile *tmpfptr = NULL;
if(*status != 0) return(*status);
do
{
*status = fits_get_num_members(infptr,&nmembers,status);
for(i = 1; i <= nmembers && *status == 0; ++i)
{
*status = fits_open_member(infptr,i,&tmpfptr,status);
*status = fits_add_group_member(outfptr,tmpfptr,0,status);
if(*status == HDU_ALREADY_MEMBER) *status = 0;
if(tmpfptr != NULL)
{
fits_close_file(tmpfptr,status);
tmpfptr = NULL;
}
}
if(*status != 0) continue;
if(mgopt == OPT_MRG_MOV)
*status = fits_remove_group(infptr,OPT_RM_GPT,status);
}while(0);
if(tmpfptr != NULL)
{
fits_close_file(tmpfptr,status);
}
return(*status);
}
int ffgtcm(fitsfile *gfptr,
int cmopt,
int *status)
{
long i;
long nmembers = 0;
char keyvalue[FLEN_VALUE];
char comment[FLEN_COMMENT];
fitsfile *mfptr = NULL;
if(*status != 0) return(*status);
do
{
if(cmopt != OPT_CMT_MBR && cmopt != OPT_CMT_MBR_DEL)
{
*status = BAD_OPTION;
ffpmsg("Invalid value for cmopt parameter specified (ffgtcm)");
continue;
}
*status = fits_get_num_members(gfptr,&nmembers,status);
for(i = 1; i <= nmembers && *status == 0; ++i)
{
*status = fits_open_member(gfptr,i,&mfptr,status);
if(*status != 0) continue;
*status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status);
if(*status == KEY_NO_EXIST)
{
*status = 0;
continue;
}
prepare_keyvalue(keyvalue);
if(*status != 0) continue;
if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
{
*status = fits_merge_groups(mfptr,gfptr,OPT_MRG_COPY,status);
*status = fits_close_file(mfptr,status);
mfptr = NULL;
if(cmopt == OPT_CMT_MBR)
*status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status);
else
*status = fits_remove_member(gfptr,i,OPT_RM_MBR,status);
}
else
{
*status = fits_close_file(mfptr,status);
mfptr = NULL;
}
}
}while(0);
return(*status);
}
int ffgtvf(fitsfile *gfptr,
long *firstfailed,
int *status)
{
long i;
long nmembers = 0;
long ngroups = 0;
char errstr[FLEN_VALUE];
fitsfile *fptr = NULL;
if(*status != 0) return(*status);
*firstfailed = 0;
do
{
*status = fits_get_num_members(gfptr,&nmembers,status);
for(i = 1; i <= nmembers && *status == 0; ++i)
{
*status = fits_open_member(gfptr,i,&fptr,status);
fits_close_file(fptr,status);
}
if(*status != 0)
{
*firstfailed = i;
snprintf(errstr,FLEN_VALUE,"Group table verify failed for member %ld (ffgtvf)",
i);
ffpmsg(errstr);
continue;
}
*status = fits_get_num_groups(gfptr,&ngroups,status);
for(i = 1; i <= ngroups && *status == 0; ++i)
{
*status = fits_open_group(gfptr,i,&fptr,status);
fits_close_file(fptr,status);
}
if(*status != 0)
{
*firstfailed = -1*i;
snprintf(errstr,FLEN_VALUE,
"Group table verify failed for GRPID index %ld (ffgtvf)",i);
ffpmsg(errstr);
continue;
}
}while(0);
return(*status);
}
int ffgtop(fitsfile *mfptr,
int grpid,
fitsfile **gfptr,
int *status)
{
int i;
int found;
long ngroups = 0;
long grpExtver = 0;
char keyword[FLEN_KEYWORD];
char keyvalue[FLEN_FILENAME];
char *tkeyvalue;
char location[FLEN_FILENAME];
char location1[FLEN_FILENAME];
char location2[FLEN_FILENAME];
char comment[FLEN_COMMENT];
char *url[2];
if(*status != 0) return(*status);
do
{
*gfptr = NULL;
*status = fits_get_num_groups(mfptr,&ngroups,status);
if(grpid > ngroups)
{
*status = BAD_GROUP_ID;
snprintf(comment,FLEN_COMMENT,
"GRPID index %d larger total GRPID keywords %ld (ffgtop)",
grpid,ngroups);
ffpmsg(comment);
continue;
}
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",grpid);
*status = fits_read_key_lng(mfptr,keyword,&grpExtver,comment,status);
if(*status != 0) continue;
do
{
if(grpExtver > 0)
{
*status = fits_reopen_file(mfptr,gfptr,status);
continue;
}
else if(grpExtver == 0)
{
*status = BAD_GROUP_ID;
snprintf(comment,FLEN_COMMENT,"Invalid value of %ld for GRPID%d (ffgtop)",
grpExtver,grpid);
ffpmsg(comment);
continue;
}
grpExtver = -1*grpExtver;
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",grpid);
*status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment,
status);
if (0 == *status) {
strcpy(keyvalue,tkeyvalue);
free(tkeyvalue);
}
if(*status == KEY_NO_EXIST)
{
*status = BAD_GROUP_ID;
snprintf(comment,FLEN_COMMENT,"Cannot find GRPLC%d keyword (ffgtop)",
grpid);
ffpmsg(comment);
continue;
}
prepare_keyvalue(keyvalue);
if(fits_is_url_absolute(keyvalue))
{
ffpmsg("Try to open group table file as absolute URL (ffgtop)");
*status = fits_open_file(gfptr,keyvalue,READWRITE,status);
if(*status == 0) continue;
ffpmsg("OK, try open group table file as READONLY (ffgtop)");
*status = 0;
*status = fits_open_file(gfptr,keyvalue,READONLY,status);
continue;
}
*status = fits_url2path(keyvalue,location1,status);
*status = fits_open_file(gfptr,location1,READWRITE,status);
if(*status == 0) continue;
ffpmsg("OK, try open group table file as READONLY (ffgtop)");
*status = 0;
*status = fits_open_file(gfptr,location1,READONLY,status);
if(*status == 0) continue;
*status = 0;
url[0] = location1; url[1] = location2;
*status = fits_get_url(mfptr,url[0],url[1],NULL,NULL,NULL,status);
for(i = 0, found = 0, *gfptr = NULL; i < 2 && !found; ++i)
{
if(*url[i] == 0) continue;
*status = fits_relurl2url(url[i],keyvalue,location,status);
if(*status != 0)
{
*status = 0;
continue;
}
if(! fits_is_url_absolute(location))
{
*status = fits_url2path(location,url[i],status);
strcpy(location,url[i]);
}
*status = fits_open_file(gfptr,location,READWRITE,status);
if(*status != 0)
{
ffpmsg("opening file as READWRITE failed (ffgtop)");
ffpmsg("OK, try to open file as READONLY (ffgtop)");
*status = 0;
*status = fits_open_file(gfptr,location,READONLY,status);
}
if(*status == 0)
found = 1;
else
*status = 0;
}
}while(0);
if(*status != 0) continue;
if(*gfptr == NULL)
{
ffpmsg("Cannot open or find grouping table FITS file (ffgtop)");
*status = GROUP_NOT_FOUND;
continue;
}
*status = fits_movnam_hdu(*gfptr,ANY_HDU,"GROUPING",(int)grpExtver,
status);
if(*status != 0) *status = GROUP_NOT_FOUND;
}while(0);
if(*status != 0 && *gfptr != NULL)
{
fits_close_file(*gfptr,status);
*gfptr = NULL;
}
return(*status);
}
int ffgtam(fitsfile *gfptr,
fitsfile *mfptr,
int hdupos,
int *status)
{
int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
int memberPosition = 0;
int grptype = 0;
int hdutype = 0;
int useLocation = 0;
int nkeys = 6;
int found;
int i;
int memberIOstate;
int groupIOstate;
int iomode;
long memberExtver = 0;
long groupExtver = 0;
long memberID = 0;
long nmembers = 0;
long ngroups = 0;
long grpid = 0;
char memberAccess1[FLEN_VALUE];
char memberAccess2[FLEN_VALUE];
char memberFileName[FLEN_FILENAME];
char memberLocation[FLEN_FILENAME];
char grplc[FLEN_FILENAME];
char *tgrplc;
char memberHDUtype[FLEN_VALUE];
char memberExtname[FLEN_VALUE];
char memberURI[] = "URL";
char groupAccess1[FLEN_VALUE];
char groupAccess2[FLEN_VALUE];
char groupFileName[FLEN_FILENAME];
char groupLocation[FLEN_FILENAME];
char tmprootname[FLEN_FILENAME], grootname[FLEN_FILENAME];
char cwd[FLEN_FILENAME];
char *keys[] = {"GRPNAME","EXTVER","EXTNAME","TFIELDS","GCOUNT","EXTEND"};
char *tmpPtr[1];
char keyword[FLEN_KEYWORD];
char card[FLEN_CARD];
unsigned char charNull[] = {'\0'};
fitsfile *tmpfptr = NULL;
int parentStatus = 0;
if(*status != 0) return(*status);
do
{
fits_file_mode(gfptr,&iomode,status);
if(iomode != READWRITE)
{
ffpmsg("cannot modify grouping table (ffgtam)");
*status = BAD_GROUP_ATTACH;
continue;
}
if(mfptr == NULL)
{
*status = fits_reopen_file(gfptr,&tmpfptr,status);
*status = fits_movabs_hdu(tmpfptr,hdupos,&hdutype,status);
if(*status != 0) continue;
}
else
tmpfptr = mfptr;
*status = fits_read_key_str(tmpfptr,"XTENSION",memberHDUtype,card,
status);
if(*status == KEY_NO_EXIST)
{
strcpy(memberHDUtype,"PRIMARY");
*status = 0;
}
prepare_keyvalue(memberHDUtype);
*status = fits_read_key_lng(tmpfptr,"EXTVER",&memberExtver,card,status);
if(*status == KEY_NO_EXIST)
{
memberExtver = 1;
*status = 0;
}
*status = fits_read_key_str(tmpfptr,"EXTNAME",memberExtname,card,
status);
if(*status == KEY_NO_EXIST)
{
memberExtname[0] = 0;
*status = 0;
}
prepare_keyvalue(memberExtname);
fits_get_hdu_num(tmpfptr,&memberPosition);
useLocation = 1;
*status = fits_get_url(tmpfptr,memberFileName,memberLocation,
memberAccess1,memberAccess2,&memberIOstate,
status);
if(strlen(memberFileName) == 0)
{
strcpy(memberFileName,memberLocation);
strcpy(memberAccess1,memberAccess2);
}
*status = fits_get_url(gfptr,groupFileName,groupLocation,
groupAccess1,groupAccess2,&groupIOstate,
status);
if(*status != 0) continue;
if(groupIOstate == 0)
{
ffpmsg("cannot modify grouping table (ffgtam)");
*status = BAD_GROUP_ATTACH;
continue;
}
if(fits_strcasecmp(groupAccess1,"file://") &&
fits_strcasecmp(memberAccess1,"file://"))
{
*cwd = 0;
}
else
{
*status = fits_get_cwd(cwd,status);
if(fits_strcasecmp(memberAccess1,"file://") == 0)
{
if(*memberFileName == '/')
{
strcpy(memberLocation,memberFileName);
}
else
{
strcpy(memberLocation,cwd);
if (strlen(memberLocation)+strlen(memberFileName)+1 >
FLEN_FILENAME-1)
{
ffpmsg("member path and filename is too long (ffgtam)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(memberLocation,"/");
strcat(memberLocation,memberFileName);
}
*status = fits_clean_url(memberLocation,memberFileName,
status);
}
if(fits_strcasecmp(groupAccess1,"file://") == 0)
{
if(*groupFileName == '/')
{
strcpy(groupLocation,groupFileName);
}
else
{
strcpy(groupLocation,cwd);
if (strlen(groupLocation)+strlen(groupFileName)+1 >
FLEN_FILENAME-1)
{
ffpmsg("group path and filename is too long (ffgtam)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(groupLocation,"/");
strcat(groupLocation,groupFileName);
}
*status = fits_clean_url(groupLocation,groupFileName,status);
}
if(fits_strcasecmp(groupAccess1,"file://") == 0 &&
fits_strcasecmp(memberAccess1,"file://") == 0)
{
fits_url2relurl(memberFileName,groupFileName,
groupLocation,status);
fits_url2relurl(groupFileName,memberFileName,
memberLocation,status);
strcpy(memberFileName,memberLocation);
strcpy(groupFileName,groupLocation);
}
}
*status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,status);
fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
if((tmpfptr->Fptr != gfptr->Fptr) &&
strncmp(tmprootname, grootname, FLEN_FILENAME))
groupExtver = -1*groupExtver;
*status = fits_get_num_members(gfptr,&nmembers,status);
do {
*status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
memberPosition,memberFileName,&memberID,status);
if(*status == MEMBER_NOT_FOUND) *status = 0;
else if(*status == 0)
{
parentStatus = HDU_ALREADY_MEMBER;
ffpmsg("Specified HDU is already a member of the Grouping table (ffgtam)");
continue;
}
else continue;
*status = fits_insert_rows(gfptr,nmembers,1,status);
++nmembers;
*status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
&locationCol,&uriCol,&grptype,status);
*tmpPtr = memberHDUtype;
if(xtensionCol != 0)
fits_write_col_str(gfptr,xtensionCol,nmembers,1,1,tmpPtr,status);
*tmpPtr = memberExtname;
if(extnameCol != 0)
{
if(strlen(memberExtname) != 0)
fits_write_col_str(gfptr,extnameCol,nmembers,1,1,tmpPtr,status);
else
fits_write_col_byt(gfptr,extnameCol,nmembers,1,1,charNull,status);
}
if(extverCol != 0)
fits_write_col_lng(gfptr,extverCol,nmembers,1,1,&memberExtver,
status);
if(positionCol != 0)
fits_write_col_int(gfptr,positionCol,nmembers,1,1,
&memberPosition,status);
*tmpPtr = memberFileName;
if(locationCol != 0)
{
fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
if((tmpfptr->Fptr != gfptr->Fptr) &&
strncmp(tmprootname, grootname, FLEN_FILENAME))
fits_write_col_str(gfptr,locationCol,nmembers,1,1,tmpPtr,status);
else
fits_write_col_byt(gfptr,locationCol,nmembers,1,1,charNull,status);
}
*tmpPtr = memberURI;
if(uriCol != 0)
{
fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
if((tmpfptr->Fptr != gfptr->Fptr) &&
strncmp(tmprootname, grootname, FLEN_FILENAME))
fits_write_col_str(gfptr,uriCol,nmembers,1,1,tmpPtr,status);
else
fits_write_col_byt(gfptr,uriCol,nmembers,1,1,charNull,status);
}
} while(0);
if(0 != *status) continue;
fits_file_mode(tmpfptr,&iomode,status);
if(memberIOstate == 0 || iomode != READWRITE)
{
ffpmsg("cannot add GRPID/LC keywords to member HDU: (ffgtam)");
ffpmsg(memberFileName);
continue;
}
*status = fits_get_num_groups(tmpfptr,&ngroups,status);
for(i = 1, found = 0; i <= ngroups && !found && *status == 0; ++i)
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups);
*status = fits_read_key_lng(tmpfptr,keyword,&grpid,card,status);
if(grpid == groupExtver)
{
if(grpid < 0)
{
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)ngroups);
*status = fits_read_key_longstr(mfptr,keyword,&tgrplc,card,
status);
if (0 == *status) {
strcpy(grplc,tgrplc);
free(tgrplc);
}
if(0 < strlen(cwd)) {
char tmp[FLEN_FILENAME];
if(!fits_is_url_absolute(grplc)) {
fits_path2url(grplc,FLEN_FILENAME,groupLocation,status);
if(groupLocation[0] != '/')
{
strcpy(tmp, cwd);
if (strlen(tmp)+strlen(groupLocation)+1 >
FLEN_FILENAME-1)
{
ffpmsg("path and group location is too long (ffgtam)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(tmp,"/");
strcat(tmp,groupLocation);
fits_clean_url(tmp,grplc,status);
}
}
if(!fits_is_url_absolute(groupFileName)) {
fits_path2url(groupFileName,FLEN_FILENAME,groupLocation,status);
if(groupLocation[0] != '/')
{
strcpy(tmp, cwd);
if (strlen(tmp)+strlen(groupLocation)+1 >
FLEN_FILENAME-1)
{
ffpmsg("path and group location is too long (ffgtam)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(tmp,"/");
strcat(tmp,groupLocation);
fits_clean_url(tmp,groupLocation,status);
}
}
}
if(strcmp(grplc,groupLocation) == 0) found = 1;
}
else
{
found = 1;
}
}
}
if(found)
{
ffpmsg("HDU already has GRPID/LC keywords for group table (ffgtam)");
continue;
}
if(ngroups == 0)
{
for(i = 0, *status = KEY_NO_EXIST;
i < nkeys && *status == KEY_NO_EXIST; ++i)
{
*status = 0;
*status = fits_read_card(tmpfptr,keys[i],card,status);
}
if(*status == KEY_NO_EXIST)
{
*status = 0;
fits_get_hdrspace(tmpfptr,&nkeys,&i,status);
ffgrec(tmpfptr,nkeys,card,status);
}
if(*status != 0) continue;
}
++ngroups;
fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
if((tmpfptr->Fptr == gfptr->Fptr) ||
strncmp(tmprootname, grootname, FLEN_FILENAME) == 0)
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups);
fits_insert_key_lng(tmpfptr,keyword,groupExtver,
"EXTVER of Group containing this HDU",status);
}
else
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups);
fits_insert_key_lng(tmpfptr,keyword,groupExtver,
"EXTVER of Group containing this HDU",status);
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)ngroups);
fits_insert_key_longstr(tmpfptr,keyword,groupFileName,
"URL of file containing Group",status);
fits_write_key_longwarn(tmpfptr,status);
}
}while(0);
if(mfptr == NULL)
{
*status = fits_close_file(tmpfptr,status);
}
*status = 0 == *status ? parentStatus : *status;
return(*status);
}
int ffgtnm(fitsfile *gfptr,
long *nmembers,
int *status)
{
char keyvalue[FLEN_VALUE];
char comment[FLEN_COMMENT];
if(*status != 0) return(*status);
*status = fits_read_keyword(gfptr,"EXTNAME",keyvalue,comment,status);
if(*status == KEY_NO_EXIST)
*status = NOT_GROUP_TABLE;
else
{
prepare_keyvalue(keyvalue);
if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
{
*status = NOT_GROUP_TABLE;
ffpmsg("Specified HDU is not a Grouping table (ffgtnm)");
}
*status = fits_read_key_lng(gfptr,"NAXIS2",nmembers,comment,status);
}
return(*status);
}
int ffgmng(fitsfile *mfptr,
long *ngroups,
int *status)
{
int offset;
int index;
int newIndex;
int i;
long grpid;
char *inclist[] = {"GRPID#"};
char keyword[FLEN_KEYWORD];
char newKeyword[FLEN_KEYWORD];
char card[FLEN_CARD];
char comment[FLEN_COMMENT];
char *tkeyvalue;
if(*status != 0) return(*status);
*ngroups = 0;
*status = ffgrec(mfptr,0,card,status);
while(*status == 0)
{
*status = fits_find_nextkey(mfptr,inclist,1,NULL,0,card,status);
if(*status != 0) continue;
++(*ngroups);
}
if(*status == KEY_NO_EXIST) *status = 0;
for(index = 1, offset = 0, i = 1; i <= *ngroups && *status == 0; ++index)
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",index);
*status = fits_read_key_lng(mfptr,keyword,&grpid,card,status);
if(*status == KEY_NO_EXIST)
{
*status = 0;
++offset;
}
else
{
++i;
if(offset > 0)
{
newIndex = index - offset;
snprintf(newKeyword,FLEN_KEYWORD,"GRPID%d",newIndex);
fits_modify_name(mfptr,keyword,newKeyword,status);
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",index);
snprintf(newKeyword,FLEN_KEYWORD,"GRPLC%d",newIndex);
*status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment,
status);
if (0 == *status) {
fits_delete_key(mfptr,keyword,status);
fits_insert_key_longstr(mfptr,newKeyword,tkeyvalue,comment,status);
fits_write_key_longwarn(mfptr,status);
free(tkeyvalue);
}
if(*status == KEY_NO_EXIST) *status = 0;
}
}
}
return(*status);
}
int ffgmop(fitsfile *gfptr,
long member,
fitsfile **mfptr,
int *status)
{
int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
int grptype,hdutype;
int dummy;
long hdupos = 0;
long extver = 0;
char xtension[FLEN_VALUE];
char extname[FLEN_VALUE];
char uri[FLEN_VALUE];
char grpLocation1[FLEN_FILENAME];
char grpLocation2[FLEN_FILENAME];
char mbrLocation1[FLEN_FILENAME];
char mbrLocation2[FLEN_FILENAME];
char mbrLocation3[FLEN_FILENAME];
char cwd[FLEN_FILENAME];
char card[FLEN_CARD];
char nstr[] = {'\0'};
char *tmpPtr[1];
if(*status != 0) return(*status);
do
{
*status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
&locationCol,&uriCol,&grptype,status);
if(*status != 0) continue;
*status = ffvcfm(gfptr,xtensionCol,extnameCol,extverCol,positionCol,
locationCol,uriCol,status);
if(*status != 0) continue;
tmpPtr[0] = xtension;
if(xtensionCol != 0)
{
*status = fits_read_col_str(gfptr,xtensionCol,member,1,1,nstr,
tmpPtr,&dummy,status);
if(fits_strcasecmp(xtension,"PRIMARY") == 0) hdutype = IMAGE_HDU;
else if(fits_strcasecmp(xtension,"IMAGE") == 0) hdutype = IMAGE_HDU;
else if(fits_strcasecmp(xtension,"TABLE") == 0) hdutype = ASCII_TBL;
else if(fits_strcasecmp(xtension,"BINTABLE") == 0) hdutype = BINARY_TBL;
else hdutype = ANY_HDU;
}
tmpPtr[0] = extname;
if(extnameCol != 0)
*status = fits_read_col_str(gfptr,extnameCol,member,1,1,nstr,
tmpPtr,&dummy,status);
if(extverCol != 0)
*status = fits_read_col_lng(gfptr,extverCol,member,1,1,0,
(long*)&extver,&dummy,status);
if(positionCol != 0)
*status = fits_read_col_lng(gfptr,positionCol,member,1,1,0,
(long*)&hdupos,&dummy,status);
tmpPtr[0] = mbrLocation1;
if(locationCol != 0)
*status = fits_read_col_str(gfptr,locationCol,member,1,1,nstr,
tmpPtr,&dummy,status);
tmpPtr[0] = uri;
if(uriCol != 0)
*status = fits_read_col_str(gfptr,uriCol,member,1,1,nstr,
tmpPtr,&dummy,status);
if(*status != 0) continue;
switch(grptype)
{
case GT_ID_POS:
case GT_ID_REF:
case GT_ID_ALL:
*status = fits_reopen_file(gfptr,mfptr,status);
break;
case GT_ID_REF_URI:
case GT_ID_POS_URI:
case GT_ID_ALL_URI:
if(strlen(mbrLocation1) == 0)
{
*status = fits_reopen_file(gfptr,mfptr,status);
}
else
{
if(fits_strcasecmp(uri,"URL") != 0)
{
*status = FILE_NOT_OPENED;
snprintf(card,FLEN_CARD,
"Cannot open member HDU file with URI type %s (ffgmop)",
uri);
ffpmsg(card);
continue;
}
do
{
if(fits_is_url_absolute(mbrLocation1))
{
ffpmsg("member URL is absolute, try open R/W (ffgmop)");
*status = fits_open_file(mfptr,mbrLocation1,READWRITE,
status);
if(*status == 0) continue;
*status = 0;
ffpmsg("OK, now try to open read-only (ffgmop)");
*status = fits_open_file(mfptr,mbrLocation1,READONLY,
status);
continue;
}
ffpmsg("Member URL is of type FILE (ffgmop)");
if(*mbrLocation1 == '/')
{
ffpmsg("Member URL specifies abs file path (ffgmop)");
*status = fits_url2path(mbrLocation1,mbrLocation2,
status);
ffpmsg("Try to open member URL in R/W mode (ffgmop)");
*status = fits_open_file(mfptr,mbrLocation2,READWRITE,
status);
if(*status == 0) continue;
*status = 0;
ffpmsg("OK, now try to open read-only (ffgmop)");
*status = fits_open_file(mfptr,mbrLocation2,READONLY,
status);
continue;
}
ffpmsg("Try to open member file as relative URL (ffgmop)");
*status = fits_get_url(gfptr,grpLocation1,grpLocation2,
NULL,NULL,NULL,status);
if(*grpLocation1)
{
if(! fits_is_url_absolute(grpLocation1) &&
*grpLocation1 != '/')
{
fits_get_cwd(cwd,status);
strcat(cwd,"/");
if (strlen(cwd)+strlen(grpLocation1)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and group location1 is too long (ffgmop)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(cwd,grpLocation1);
strcpy(grpLocation1,cwd);
}
*status = fits_relurl2url(grpLocation1,mbrLocation1,
mbrLocation2,status);
if(*status != 0) continue;
if(! fits_is_url_absolute(mbrLocation2))
{
*status = fits_url2path(mbrLocation2,mbrLocation3,
status);
strcpy(mbrLocation2,mbrLocation3);
}
*status = fits_open_file(mfptr,mbrLocation2,READWRITE,
status);
if(*status == 0) continue;
*status = 0;
ffpmsg("now try to open file as READONLY (ffgmop)");
*status = fits_open_file(mfptr,mbrLocation2,READONLY,
status);
if(*status == 0) continue;
*status = 0;
}
if(*grpLocation2)
{
if(! fits_is_url_absolute(grpLocation2) &&
*grpLocation2 != '/')
{
fits_get_cwd(cwd,status);
if (strlen(cwd)+strlen(grpLocation2)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and group location2 is too long (ffgmop)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(cwd,"/");
strcat(cwd,grpLocation2);
strcpy(grpLocation2,cwd);
}
*status = fits_relurl2url(grpLocation2,mbrLocation1,
mbrLocation2,status);
if(*status != 0) continue;
if(! fits_is_url_absolute(mbrLocation2))
{
*status = fits_url2path(mbrLocation2,mbrLocation3,
status);
strcpy(mbrLocation2,mbrLocation3);
}
*status = fits_open_file(mfptr,mbrLocation2,READWRITE,
status);
if(*status == 0) continue;
*status = 0;
ffpmsg("now try to open file as READONLY (ffgmop)");
*status = fits_open_file(mfptr,mbrLocation2,READONLY,
status);
if(*status == 0) continue;
*status = 0;
}
ffpmsg("Cannot open member HDU FITS file (ffgmop)");
*status = MEMBER_NOT_FOUND;
}while(0);
}
break;
default:
break;
}
if(*status != 0) continue;
switch(grptype)
{
case GT_ID_POS:
case GT_ID_POS_URI:
*status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,status);
break;
case GT_ID_REF:
case GT_ID_REF_URI:
*status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status);
if(*status == BAD_HDU_NUM)
{
*status = MEMBER_NOT_FOUND;
ffpmsg("Cannot find specified member HDU (ffgmop)");
}
break;
case GT_ID_ALL:
case GT_ID_ALL_URI:
if(strlen(xtension) > 0 && strlen(extname) > 0 && extver > 0)
{
*status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status);
if(*status == BAD_HDU_NUM)
{
*status = MEMBER_NOT_FOUND;
ffpmsg("Cannot find specified member HDU (ffgmop)");
}
}
else
{
*status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,
status);
if(*status == END_OF_FILE) *status = MEMBER_NOT_FOUND;
}
break;
default:
break;
}
}while(0);
if(*status != 0 && *mfptr != NULL)
{
fits_close_file(*mfptr,status);
}
return(*status);
}
int ffgmcp(fitsfile *gfptr,
fitsfile *mfptr,
long member,
int cpopt,
int *status)
{
int numkeys = 0;
int keypos = 0;
int hdunum = 0;
int hdutype = 0;
int i;
char *incList[] = {"GRPID#","GRPLC#"};
char extname[FLEN_VALUE];
char card[FLEN_CARD];
char comment[FLEN_COMMENT];
char keyname[FLEN_CARD];
char value[FLEN_CARD];
fitsfile *tmpfptr = NULL;
if(*status != 0) return(*status);
do
{
*status = fits_open_member(gfptr,member,&tmpfptr,status);
if(*status != 0) continue;
*status = fits_read_key_str(tmpfptr,"EXTNAME",extname,comment,status);
if(*status == KEY_NO_EXIST)
{
extname[0] = 0;
*status = 0;
}
else if(*status != 0) continue;
prepare_keyvalue(extname);
if(fits_strcasecmp(extname,"GROUPING") == 0)
*status = fits_copy_group(tmpfptr,mfptr,OPT_GCP_GPT,status);
else
{
*status = fits_copy_hdu(tmpfptr,mfptr,0,status);
ffgrec(mfptr,0,card,status);
while(*status == 0)
{
*status = fits_find_nextkey(mfptr,incList,2,NULL,0,card,status);
*status = fits_get_hdrpos(mfptr,&numkeys,&keypos,status);
*status = fits_read_keyn(mfptr,keypos-1,keyname,value,
comment,status);
*status = fits_read_record(mfptr,keypos-1,card,status);
*status = fits_delete_key(mfptr,keyname,status);
}
if(*status == KEY_NO_EXIST) *status = 0;
if(*status != 0) continue;
}
if(strlen(extname) == 0)
{
if(fits_get_hdu_num(tmpfptr,&hdunum) == 1)
{
strcpy(extname,"PRIMARY");
*status = fits_write_key_str(mfptr,"EXTNAME",extname,
"HDU was Formerly a Primary Array",
status);
}
else
{
strcpy(extname,"DEFAULT");
*status = fits_write_key_str(mfptr,"EXTNAME",extname,
"default EXTNAME set by CFITSIO",
status);
}
}
fits_get_hdu_num(mfptr,&hdunum);
fits_get_hdu_type(mfptr,&hdutype,status);
*status = fits_modify_key_lng(mfptr,"EXTVER",0,NULL,status);
if(*status == KEY_NO_EXIST)
{
*status = 0;
*status = fits_read_key_str(mfptr,"EXTNAME",extname,comment,
status);
*status = fits_insert_key_lng(mfptr,"EXTVER",0,
"Extension version ID",status);
}
if(*status != 0) continue;
for(i = 1; fits_movnam_hdu(mfptr,hdutype,extname,i,status) == 0; ++i);
*status = 0;
fits_movabs_hdu(mfptr,hdunum,&hdutype,status);
*status = fits_modify_key_lng(mfptr,"EXTVER",(long)i,NULL,status);
switch(cpopt)
{
case OPT_MCP_ADD:
*status = fits_add_group_member(gfptr,mfptr,0,status);
break;
case OPT_MCP_NADD:
break;
case OPT_MCP_REPL:
*status = fits_remove_member(gfptr,member,OPT_RM_ENTRY,status);
*status = fits_add_group_member(gfptr,mfptr,0,status);
break;
default:
*status = BAD_OPTION;
ffpmsg("Invalid value specified for the cmopt parameter (ffgmcp)");
break;
}
}while(0);
if(tmpfptr != NULL)
{
fits_close_file(tmpfptr,status);
}
return(*status);
}
int ffgmtf(fitsfile *infptr,
fitsfile *outfptr,
long member,
int tfopt,
int *status)
{
fitsfile *mfptr = NULL;
if(*status != 0) return(*status);
if(tfopt != OPT_MCP_MOV && tfopt != OPT_MCP_ADD)
{
*status = BAD_OPTION;
ffpmsg("Invalid value specified for the tfopt parameter (ffgmtf)");
}
else
{
*status = fits_open_member(infptr,member,&mfptr,status);
*status = fits_add_group_member(outfptr,mfptr,0,status);
*status = fits_close_file(mfptr,status);
if(tfopt == OPT_MCP_MOV)
*status = fits_remove_member(infptr,member,OPT_RM_ENTRY,status);
}
return(*status);
}
int ffgmrm(fitsfile *gfptr,
long member,
int rmopt,
int *status)
{
int found;
int hdutype = 0;
int index;
int iomode = 0;
long i;
long ngroups = 0;
long nmembers = 0;
long groupExtver = 0;
long grpid = 0;
char grpLocation1[FLEN_FILENAME];
char grpLocation2[FLEN_FILENAME];
char grpLocation3[FLEN_FILENAME];
char cwd[FLEN_FILENAME];
char keyword[FLEN_KEYWORD];
char grplc[FLEN_FILENAME];
char *tgrplc;
char keyvalue[FLEN_VALUE];
char card[FLEN_CARD];
char *editLocation;
char mrootname[FLEN_FILENAME], grootname[FLEN_FILENAME];
fitsfile *mfptr = NULL;
if(*status != 0) return(*status);
do
{
fits_file_mode(gfptr,&iomode,status);
if(iomode != READWRITE)
{
ffpmsg("cannot modify grouping table (ffgtam)");
*status = BAD_GROUP_DETACH;
continue;
}
*status = fits_open_member(gfptr,member,&mfptr,status);
*status = fits_file_mode(mfptr,&iomode,status);
if(rmopt == OPT_RM_MBR)
{
if(fits_get_hdu_num(mfptr,&hdutype) == 1)
{
*status = BAD_HDU_NUM;
continue;
}
*status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,status);
if(*status == KEY_NO_EXIST)
{
keyvalue[0] = 0;
*status = 0;
}
prepare_keyvalue(keyvalue);
if(*status != 0) continue;
if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
{
*status = fits_get_num_members(mfptr,&nmembers,status);
for(i = nmembers; i > 0 && *status == 0; --i)
*status = fits_remove_member(mfptr,i,OPT_RM_ENTRY,status);
if(*status != 0) continue;
}
*status = ffgmul(mfptr,0,status);
if(*status != 0) continue;
fits_set_hdustruc(gfptr,status);
if(iomode != READONLY)
*status = fits_delete_hdu(mfptr,&hdutype,status);
}
else if(rmopt == OPT_RM_ENTRY)
{
if(iomode == READWRITE)
{
*status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,
status);
fits_parse_rootname(mfptr->Fptr->filename, mrootname, status);
fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
if((mfptr->Fptr != gfptr->Fptr) &&
strncmp(mrootname, grootname, FLEN_FILENAME))
groupExtver = -1*groupExtver;
*status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,
NULL,NULL,status);
if(*status != 0) continue;
*status = fits_get_cwd(cwd,status);
if(*grpLocation1 != 0 && *grpLocation1 != '/' &&
!fits_is_url_absolute(grpLocation1))
{
strcpy(grpLocation3,cwd);
if (strlen(grpLocation3)+strlen(grpLocation1)+1 >
FLEN_FILENAME-1)
{
ffpmsg("group locations are too long (ffgmrm)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(grpLocation3,"/");
strcat(grpLocation3,grpLocation1);
fits_clean_url(grpLocation3,grpLocation1,status);
}
if(*grpLocation2 != 0 && *grpLocation2 != '/' &&
!fits_is_url_absolute(grpLocation2))
{
strcpy(grpLocation3,cwd);
if (strlen(grpLocation3)+strlen(grpLocation2)+1 >
FLEN_FILENAME-1)
{
ffpmsg("group locations are too long (ffgmrm)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(grpLocation3,"/");
strcat(grpLocation3,grpLocation2);
fits_clean_url(grpLocation3,grpLocation2,status);
}
*status = fits_get_num_groups(mfptr,&ngroups,status);
*status = ffgrec(mfptr,0,card,status);
for(index = 1, found = 0; index <= ngroups && *status == 0 &&
!found; ++index)
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",index);
*status = fits_read_key_lng(mfptr,keyword,&grpid,card,
status);
if(*status != 0) continue;
if(grpid == groupExtver && grpid > 0)
{
found = index;
}
else if(grpid == groupExtver && grpid < 0)
{
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",index);
*status = fits_read_key_longstr(mfptr,keyword,&tgrplc,
card, status);
if (0 == *status) {
strcpy(grplc,tgrplc);
free(tgrplc);
}
if(*status == KEY_NO_EXIST)
{
snprintf(card,FLEN_CARD,"No GRPLC%d found for GRPID%d",
index,index);
ffpmsg(card);
*status = 0;
continue;
}
else if (*status != 0) continue;
prepare_keyvalue(grplc);
if(*grplc != 0 && !fits_is_url_absolute(grplc) &&
*grplc != '/')
{
*status = fits_file_name(mfptr,grpLocation3,status);
if (NULL != (editLocation = strrchr(grpLocation3,'/'))) {
*editLocation = '\0';
}
if (strlen(grpLocation3)+strlen(grplc)+1 >
FLEN_FILENAME-1)
{
ffpmsg("group locations are too long (ffgmrm)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(grpLocation3,"/");
strcat(grpLocation3,grplc);
*status = fits_clean_url(grpLocation3,grplc,
status);
}
if(strcmp(grplc,grpLocation1) == 0 ||
strcmp(grplc,grpLocation2) == 0)
found = index;
}
}
if(found != 0)
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",found);
*status = fits_delete_key(mfptr,keyword,status);
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",found);
*status = fits_delete_key(mfptr,keyword,status);
*status = 0;
*status = fits_get_num_groups(mfptr,&ngroups,status);
}
}
*status = fits_delete_rows(gfptr,member,1,status);
}
else
{
*status = BAD_OPTION;
ffpmsg("Invalid value specified for the rmopt parameter (ffgmrm)");
}
}while(0);
if(mfptr != NULL)
{
fits_close_file(mfptr,status);
}
return(*status);
}
int ffgtgc(fitsfile *gfptr,
int *xtensionCol,
int *extnameCol,
int *extverCol,
int *positionCol,
int *locationCol,
int *uriCol,
int *grptype,
int *status)
{
char keyvalue[FLEN_VALUE];
char comment[FLEN_COMMENT];
if(*status != 0) return(*status);
do
{
*status = fits_read_key_str(gfptr,"EXTNAME",keyvalue,comment,status);
if(*status == KEY_NO_EXIST)
{
*status = NOT_GROUP_TABLE;
ffpmsg("Specified HDU is not a Grouping Table (ffgtgc)");
}
if(*status != 0) continue;
prepare_keyvalue(keyvalue);
if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
{
*status = NOT_GROUP_TABLE;
continue;
}
*status = fits_get_colnum(gfptr,CASESEN,"MEMBER_XTENSION",xtensionCol,
status);
if(*status == COL_NOT_FOUND)
{
*status = 0;
*xtensionCol = 0;
}
if(*status != 0) continue;
*status = fits_get_colnum(gfptr,CASESEN,"MEMBER_NAME",extnameCol,status);
if(*status == COL_NOT_FOUND)
{
*status = 0;
*extnameCol = 0;
}
if(*status != 0) continue;
*status = fits_get_colnum(gfptr,CASESEN,"MEMBER_VERSION",extverCol,
status);
if(*status == COL_NOT_FOUND)
{
*status = 0;
*extverCol = 0;
}
if(*status != 0) continue;
*status = fits_get_colnum(gfptr,CASESEN,"MEMBER_POSITION",positionCol,
status);
if(*status == COL_NOT_FOUND)
{
*status = 0;
*positionCol = 0;
}
if(*status != 0) continue;
*status = fits_get_colnum(gfptr,CASESEN,"MEMBER_LOCATION",locationCol,
status);
if(*status == COL_NOT_FOUND)
{
*status = 0;
*locationCol = 0;
}
if(*status != 0) continue;
*status = fits_get_colnum(gfptr,CASESEN,"MEMBER_URI_TYPE",uriCol,
status);
if(*status == COL_NOT_FOUND)
{
*status = 0;
*uriCol = 0;
}
if(*status != 0) continue;
if(*xtensionCol && *extnameCol && *extverCol && *positionCol &&
*locationCol && *uriCol)
*grptype = GT_ID_ALL_URI;
else if(*xtensionCol && *extnameCol && *extverCol &&
*locationCol && *uriCol)
*grptype = GT_ID_REF_URI;
else if(*xtensionCol && *extnameCol && *extverCol && *positionCol)
*grptype = GT_ID_ALL;
else if(*xtensionCol && *extnameCol && *extverCol)
*grptype = GT_ID_REF;
else if(*positionCol && *locationCol && *uriCol)
*grptype = GT_ID_POS_URI;
else if(*positionCol)
*grptype = GT_ID_POS;
else
*status = NOT_GROUP_TABLE;
}while(0);
if(*status == COL_NOT_UNIQUE)
{
*status = NOT_GROUP_TABLE;
ffpmsg("Specified HDU has multipule Group table cols defined (ffgtgc)");
}
return(*status);
}
int ffvcfm(fitsfile *gfptr, int xtensionCol, int extnameCol, int extverCol,
int positionCol, int locationCol, int uriCol, int *status)
{
int typecode=0;
long repeat=0, width=0;
if (*status != 0) return (*status);
do {
if (xtensionCol)
{
fits_get_coltype(gfptr, xtensionCol, &typecode, &repeat, &width, status);
if (*status || typecode != TSTRING || repeat != width || repeat > 8)
{
if (*status==0) *status=NOT_GROUP_TABLE;
ffpmsg("Wrong format for Grouping xtension col. (ffvcfm)");
continue;
}
}
if (extnameCol)
{
fits_get_coltype(gfptr, extnameCol, &typecode, &repeat, &width, status);
if (*status || typecode != TSTRING || repeat != width || repeat > 32)
{
if (*status==0) *status=NOT_GROUP_TABLE;
ffpmsg("Wrong format for Grouping name col. (ffvcfm)");
continue;
}
}
if (extverCol)
{
fits_get_coltype(gfptr, extverCol, &typecode, &repeat, &width, status);
if (*status || typecode != TINT32BIT || repeat > 1)
{
if (*status==0) *status=NOT_GROUP_TABLE;
ffpmsg("Wrong format for Grouping version col. (ffvcfm)");
continue;
}
}
if (positionCol)
{
fits_get_coltype(gfptr, positionCol, &typecode, &repeat, &width, status);
if (*status || typecode != TINT32BIT || repeat > 1)
{
if (*status==0) *status=NOT_GROUP_TABLE;
ffpmsg("Wrong format for Grouping position col. (ffvcfm)");
continue;
}
}
if (locationCol)
{
fits_get_coltype(gfptr, locationCol, &typecode, &repeat, &width, status);
if (*status || typecode != TSTRING || repeat != width || repeat > 256)
{
if (*status==0) *status=NOT_GROUP_TABLE;
ffpmsg("Wrong format for Grouping location col. (ffvcfm)");
continue;
}
}
if (uriCol)
{
fits_get_coltype(gfptr, uriCol, &typecode, &repeat, &width, status);
if (*status || typecode != TSTRING || repeat != width || repeat > 3)
{
if (*status==0) *status=NOT_GROUP_TABLE;
ffpmsg("Wrong format for Grouping URI col. (ffvcfm)");
continue;
}
}
} while (0);
return (*status);
}
int ffgtdc(int grouptype,
int xtensioncol,
int extnamecol,
int extvercol,
int positioncol,
int locationcol,
int uricol,
char *ttype[],
char *tform[],
int *ncols,
int *status)
{
int i = 0;
char xtension[] = "MEMBER_XTENSION";
char xtenTform[] = "8A";
char name[] = "MEMBER_NAME";
char nameTform[] = "32A";
char version[] = "MEMBER_VERSION";
char verTform[] = "1J";
char position[] = "MEMBER_POSITION";
char posTform[] = "1J";
char URI[] = "MEMBER_URI_TYPE";
char URITform[] = "3A";
char location[] = "MEMBER_LOCATION";
char locTform[] = "256A";
if(*status != 0) return(*status);
switch(grouptype)
{
case GT_ID_ALL_URI:
if(xtensioncol == 0)
{
strcpy(ttype[i],xtension);
strcpy(tform[i],xtenTform);
++i;
}
if(extnamecol == 0)
{
strcpy(ttype[i],name);
strcpy(tform[i],nameTform);
++i;
}
if(extvercol == 0)
{
strcpy(ttype[i],version);
strcpy(tform[i],verTform);
++i;
}
if(positioncol == 0)
{
strcpy(ttype[i],position);
strcpy(tform[i],posTform);
++i;
}
if(locationcol == 0)
{
strcpy(ttype[i],location);
strcpy(tform[i],locTform);
++i;
}
if(uricol == 0)
{
strcpy(ttype[i],URI);
strcpy(tform[i],URITform);
++i;
}
break;
case GT_ID_REF:
if(xtensioncol == 0)
{
strcpy(ttype[i],xtension);
strcpy(tform[i],xtenTform);
++i;
}
if(extnamecol == 0)
{
strcpy(ttype[i],name);
strcpy(tform[i],nameTform);
++i;
}
if(extvercol == 0)
{
strcpy(ttype[i],version);
strcpy(tform[i],verTform);
++i;
}
break;
case GT_ID_POS:
if(positioncol == 0)
{
strcpy(ttype[i],position);
strcpy(tform[i],posTform);
++i;
}
break;
case GT_ID_ALL:
if(xtensioncol == 0)
{
strcpy(ttype[i],xtension);
strcpy(tform[i],xtenTform);
++i;
}
if(extnamecol == 0)
{
strcpy(ttype[i],name);
strcpy(tform[i],nameTform);
++i;
}
if(extvercol == 0)
{
strcpy(ttype[i],version);
strcpy(tform[i],verTform);
++i;
}
if(positioncol == 0)
{
strcpy(ttype[i],position);
strcpy(tform[i], posTform);
++i;
}
break;
case GT_ID_REF_URI:
if(xtensioncol == 0)
{
strcpy(ttype[i],xtension);
strcpy(tform[i],xtenTform);
++i;
}
if(extnamecol == 0)
{
strcpy(ttype[i],name);
strcpy(tform[i],nameTform);
++i;
}
if(extvercol == 0)
{
strcpy(ttype[i],version);
strcpy(tform[i],verTform);
++i;
}
if(locationcol == 0)
{
strcpy(ttype[i],location);
strcpy(tform[i],locTform);
++i;
}
if(uricol == 0)
{
strcpy(ttype[i],URI);
strcpy(tform[i],URITform);
++i;
}
break;
case GT_ID_POS_URI:
if(positioncol == 0)
{
strcpy(ttype[i],position);
strcpy(tform[i],posTform);
++i;
}
if(locationcol == 0)
{
strcpy(ttype[i],location);
strcpy(tform[i],locTform);
++i;
}
if(uricol == 0)
{
strcpy(ttype[i],URI);
strcpy(tform[i],URITform);
++i;
}
break;
default:
*status = BAD_OPTION;
ffpmsg("Invalid value specified for the grouptype parameter (ffgtdc)");
break;
}
*ncols = i;
return(*status);
}
int ffgmul(fitsfile *mfptr,
int rmopt,
int *status)
{
int memberPosition = 0;
int iomode;
long index;
long ngroups = 0;
long memberExtver = 0;
long memberID = 0;
char mbrLocation1[FLEN_FILENAME];
char mbrLocation2[FLEN_FILENAME];
char memberHDUtype[FLEN_VALUE];
char memberExtname[FLEN_VALUE];
char keyword[FLEN_KEYWORD];
char card[FLEN_CARD];
fitsfile *gfptr = NULL;
if(*status != 0) return(*status);
do
{
*status = fits_read_key_str(mfptr,"XTENSION",memberHDUtype,card,status);
if(*status == KEY_NO_EXIST)
{
strcpy(memberHDUtype,"PRIMARY");
*status = 0;
}
prepare_keyvalue(memberHDUtype);
*status = fits_read_key_lng(mfptr,"EXTVER",&memberExtver,card,status);
if(*status == KEY_NO_EXIST)
{
memberExtver = 1;
*status = 0;
}
*status = fits_read_key_str(mfptr,"EXTNAME",memberExtname,card,status);
if(*status == KEY_NO_EXIST)
{
memberExtname[0] = 0;
*status = 0;
}
prepare_keyvalue(memberExtname);
fits_get_hdu_num(mfptr,&memberPosition);
*status = fits_get_url(mfptr,mbrLocation1,mbrLocation2,NULL,NULL,
NULL,status);
if(*status != 0) continue;
*status = fits_get_num_groups(mfptr,&ngroups,status);
for(index = 1; index <= ngroups && *status == 0; ++index)
{
*status = fits_open_group(mfptr,index,&gfptr,status);
if(*status != 0)
{
*status = 0;
snprintf(card,FLEN_CARD,"Cannot open the %dth group table (ffgmul)",
(int)index);
ffpmsg(card);
continue;
}
fits_file_mode(gfptr,&iomode,status);
if(iomode != READWRITE)
{
snprintf(card,FLEN_CARD,"The %dth group cannot be modified (ffgtam)",
(int)index);
ffpmsg(card);
continue;
}
memberID = 0;
if(strlen(mbrLocation1) != 0)
{
*status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
memberPosition,mbrLocation1,&memberID,status);
}
if(*status == MEMBER_NOT_FOUND && strlen(mbrLocation2) != 0)
{
*status = 0;
*status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
memberPosition,mbrLocation2,&memberID,status);
}
if(*status == 0)
*status = fits_delete_rows(gfptr,memberID,1,status);
if(*status == MEMBER_NOT_FOUND)
{
ffpmsg("cannot locate member's entry in group table (ffgmul)");
}
*status = 0;
if(gfptr != NULL)
{
fits_close_file(gfptr,status);
gfptr = NULL;
}
}
if(*status != 0) continue;
if(rmopt != 0)
{
fits_file_mode(mfptr,&iomode,status);
if(iomode == READONLY)
{
ffpmsg("Cannot modify member HDU, opened READONLY (ffgmul)");
continue;
}
for(index = 1; index <= ngroups && *status == 0; ++index)
{
snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)index);
fits_delete_key(mfptr,keyword,status);
snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)index);
fits_delete_key(mfptr,keyword,status);
if(*status == KEY_NO_EXIST) *status = 0;
}
}
}while(0);
if(gfptr != NULL)
{
fits_close_file(gfptr,status);
}
return(*status);
}
int ffgmf(fitsfile *gfptr,
char *xtension,
char *extname,
int extver,
int position,
char *location,
long *member,
int *status)
{
int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
int mposition = 0;
int grptype;
int dummy;
int i;
long nmembers = 0;
long mextver = 0;
char charBuff1[FLEN_FILENAME];
char charBuff2[FLEN_FILENAME];
char tmpLocation[FLEN_FILENAME];
char mbrLocation1[FLEN_FILENAME];
char mbrLocation2[FLEN_FILENAME];
char mbrLocation3[FLEN_FILENAME];
char grpLocation1[FLEN_FILENAME];
char grpLocation2[FLEN_FILENAME];
char cwd[FLEN_FILENAME];
char nstr[] = {'\0'};
char *tmpPtr[2];
if(*status != 0) return(*status);
*member = 0;
tmpPtr[0] = charBuff1;
tmpPtr[1] = charBuff2;
if(*status != 0) return(*status);
if(location == NULL)
{
*tmpLocation = 0;
}
else if(*location == 0)
{
*tmpLocation = 0;
}
else if(!fits_is_url_absolute(location))
{
fits_path2url(location,FLEN_FILENAME,tmpLocation,status);
if(*tmpLocation != '/')
{
fits_get_cwd(cwd,status);
if (strlen(cwd)+strlen(tmpLocation)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and location are too long (ffgmf)");
return (*status = URL_PARSE_ERROR);
}
strcat(cwd,"/");
strcat(cwd,tmpLocation);
fits_clean_url(cwd,tmpLocation,status);
}
}
else
strcpy(tmpLocation,location);
*status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
&locationCol,&uriCol,&grptype,status);
*status = fits_get_num_members(gfptr,&nmembers,status);
for(i = 1; i <= nmembers && *member == 0 && *status == 0; ++i)
{
if(xtensionCol != 0)
{
fits_read_col_str(gfptr,xtensionCol,i,1,1,nstr,tmpPtr,&dummy,status);
if(fits_strcasecmp(tmpPtr[0],xtension) != 0) continue;
}
if(extnameCol != 0)
{
fits_read_col_str(gfptr,extnameCol,i,1,1,nstr,tmpPtr,&dummy,status);
if(fits_strcasecmp(tmpPtr[0],extname) != 0) continue;
}
if(extverCol != 0)
{
fits_read_col_lng(gfptr,extverCol,i,1,1,0,
(long*)&mextver,&dummy,status);
if(extver != mextver) continue;
}
if(positionCol != 0 &&
(grptype == GT_ID_POS || grptype == GT_ID_POS_URI))
{
fits_read_col_int(gfptr,positionCol,i,1,1,0,
&mposition,&dummy,status);
if(position != mposition) continue;
}
if(location == NULL)
{
ffpmsg("NULL Location string given ==> ignore location (ffgmf)");
*member = i;
continue;
}
if(locationCol != 0)
{
fits_read_col_str(gfptr,locationCol,i,1,1,nstr,tmpPtr,&dummy,status);
strcpy(mbrLocation1,tmpPtr[0]);
*mbrLocation2 = 0;
}
else
*mbrLocation1 = 0;
if(*mbrLocation1 == 0)
{
*status = fits_get_url(gfptr,mbrLocation1,mbrLocation2,NULL,NULL,
NULL,status);
if(*mbrLocation1 != 0 && !fits_is_url_absolute(mbrLocation1) &&
*mbrLocation1 != '/')
{
fits_get_cwd(cwd,status);
if (strlen(cwd)+strlen(mbrLocation1)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and member locations are too long (ffgmf)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(cwd,"/");
strcat(cwd,mbrLocation1);
fits_clean_url(cwd,mbrLocation1,status);
}
if(*mbrLocation2 != 0 && !fits_is_url_absolute(mbrLocation2) &&
*mbrLocation2 != '/')
{
fits_get_cwd(cwd,status);
if (strlen(cwd)+strlen(mbrLocation2)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and member locations are too long (ffgmf)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(cwd,"/");
strcat(cwd,mbrLocation2);
fits_clean_url(cwd,mbrLocation2,status);
}
}
else if(!fits_is_url_absolute(mbrLocation1) && *mbrLocation1 != '/')
{
strcpy(mbrLocation2,mbrLocation1);
*status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,NULL,
NULL,status);
if(*grpLocation1 != 0)
{
if(!fits_is_url_absolute(grpLocation1) && *grpLocation1 != '/')
{
fits_get_cwd(cwd,status);
if (strlen(cwd)+strlen(grpLocation1)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and group locations are too long (ffgmf)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(cwd,"/");
strcat(cwd,grpLocation1);
fits_clean_url(cwd,grpLocation1,status);
}
fits_relurl2url(grpLocation1,mbrLocation1,mbrLocation3,status);
if(*status == 0)
{
strcpy(mbrLocation1,mbrLocation3);
}
else if(*status == URL_PARSE_ERROR)
{
*status = 0;
*mbrLocation1 = 0;
}
}
else
*mbrLocation1 = 0;
if(*grpLocation2 != 0)
{
if(!fits_is_url_absolute(grpLocation2) && *grpLocation2 != '/')
{
fits_get_cwd(cwd,status);
if (strlen(cwd)+strlen(grpLocation2)+1 >
FLEN_FILENAME-1)
{
ffpmsg("cwd and group locations are too long (ffgmf)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(cwd,"/");
strcat(cwd,grpLocation2);
fits_clean_url(cwd,grpLocation2,status);
}
fits_relurl2url(grpLocation2,mbrLocation2,mbrLocation3,status);
if(*status == 0)
{
strcpy(mbrLocation2,mbrLocation3);
}
else if(*status == URL_PARSE_ERROR)
{
*status = 0;
*mbrLocation2 = 0;
}
}
else
*mbrLocation2 = 0;
}
if(strcmp(mbrLocation1,tmpLocation) != 0 &&
strcmp(mbrLocation2,tmpLocation) != 0 ) continue;
*member = i;
}
if(*member == 0 && *status == 0)
{
*status = MEMBER_NOT_FOUND;
ffpmsg("Cannot find specified member HDU (ffgmf)");
}
return(*status);
}
int ffgtrmr(fitsfile *gfptr,
HDUtracker *HDU,
int *status)
{
int i;
int hdutype;
long nmembers = 0;
char keyvalue[FLEN_VALUE];
char comment[FLEN_COMMENT];
fitsfile *mfptr = NULL;
if(*status != 0) return(*status);
*status = fits_get_num_members(gfptr,&nmembers,status);
for(i = nmembers; i > 0 && *status == 0; --i)
{
*status = fits_open_member(gfptr,i,&mfptr,status);
if(*status == MEMBER_NOT_FOUND)
{
*status = 0;
continue;
}
if(*status != 0) continue;
*status = fftsad(mfptr,HDU,NULL,NULL);
if(*status == HDU_ALREADY_TRACKED)
{
*status = 0;
fits_close_file(mfptr,status);
continue;
}
else if(*status != 0) continue;
*status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status);
if(*status == KEY_NO_EXIST)
{
*status = 0;
keyvalue[0] = 0;
}
prepare_keyvalue(keyvalue);
if(*status != 0) continue;
if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
*status = ffgtrmr(mfptr,HDU,status);
if(fits_get_hdu_num(mfptr,&hdutype) == 1)
*status = ffgmul(mfptr,1,status);
else
{
*status = ffgmul(mfptr,0,status);
*status = fits_delete_hdu(mfptr,&hdutype,status);
}
fits_close_file(mfptr,status);
}
return(*status);
}
int ffgtcpr(fitsfile *infptr,
fitsfile *outfptr,
int cpopt,
HDUtracker *HDU,
int *status)
{
int i;
int nexclude = 8;
int hdutype = 0;
int groupHDUnum = 0;
int numkeys = 0;
int keypos = 0;
int startSearch = 0;
int newPosition = 0;
long nmembers = 0;
long tfields = 0;
long newTfields = 0;
char keyword[FLEN_KEYWORD];
char keyvalue[FLEN_VALUE];
char card[FLEN_CARD];
char comment[FLEN_CARD];
char *tkeyvalue;
char *includeList[] = {"*"};
char *excludeList[] = {"EXTNAME","EXTVER","GRPNAME","GRPID#","GRPLC#",
"THEAP","TDIM#","T????#"};
fitsfile *mfptr = NULL;
if(*status != 0) return(*status);
do
{
*status = fits_get_num_members(infptr,&nmembers,status);
*status = fits_read_key_str(infptr,"GRPNAME",keyvalue,card,status);
if(*status == KEY_NO_EXIST)
{
keyvalue[0] = 0;
*status = 0;
}
prepare_keyvalue(keyvalue);
*status = fits_create_group(outfptr,keyvalue,GT_ID_ALL_URI,status);
fits_get_hdu_num(outfptr,&groupHDUnum);
*status = fftsud(infptr,HDU,groupHDUnum,NULL);
switch(cpopt)
{
case OPT_GCP_GPT:
for(i = 1; i <= nmembers && *status == 0; ++i)
{
*status = fits_open_member(infptr,i,&mfptr,status);
*status = fits_add_group_member(outfptr,mfptr,0,status);
fits_close_file(mfptr,status);
mfptr = NULL;
}
break;
case OPT_GCP_ALL:
for(i = 1; i <= nmembers && *status == 0; ++i)
{
*status = fits_open_member(infptr,i,&mfptr,status);
if(*status != 0) continue;
*status = fftsad(mfptr,HDU,&newPosition,NULL);
if(*status == HDU_ALREADY_TRACKED)
{
*status = 0;
*status = fits_add_group_member(outfptr,NULL,newPosition,
status);
fits_close_file(mfptr,status);
mfptr = NULL;
continue;
}
else if(*status != 0) continue;
*status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,
status);
if(*status == KEY_NO_EXIST)
{
keyvalue[0] = 0;
*status = 0;
}
prepare_keyvalue(keyvalue);
if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
*status = ffgtcpr(mfptr,outfptr,OPT_GCP_ALL,HDU,status);
else
*status = fits_copy_member(infptr,outfptr,i,OPT_MCP_NADD,
status);
fits_get_hdu_num(outfptr,&newPosition);
if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
*status = fftsud(mfptr,HDU,newPosition,NULL);
*status = fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status);
*status = fits_add_group_member(outfptr,NULL,newPosition,status);
fits_close_file(mfptr,status);
mfptr = NULL;
}
break;
default:
*status = BAD_OPTION;
ffpmsg("Invalid value specified for cmopt parameter (ffgtcpr)");
break;
}
if(*status != 0) continue;
fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status);
*status = fits_read_card(outfptr,"TTYPE1",card,status);
*status = fits_get_hdrpos(outfptr,&numkeys,&keypos,status);
--keypos;
startSearch = 8;
while(*status == 0)
{
ffgrec(infptr,startSearch,card,status);
*status = fits_find_nextkey(infptr,includeList,1,excludeList,
nexclude,card,status);
*status = fits_get_hdrpos(infptr,&numkeys,&startSearch,status);
--startSearch;
if (strncmp(card,"GRPLC",5)) {
*status = fits_insert_record(outfptr,keypos,card,status);
} else {
*status = fits_read_record(infptr,startSearch,card,status);
card[9] = '\0';
*status = fits_read_key_longstr(infptr,card,&tkeyvalue,comment,
status);
if (0 == *status) {
fits_insert_key_longstr(outfptr,card,tkeyvalue,comment,status);
fits_write_key_longwarn(outfptr,status);
free(tkeyvalue);
}
}
++keypos;
}
if(*status == KEY_NO_EXIST)
*status = 0;
else if(*status != 0) continue;
*status = fits_read_key_lng(infptr,"TFIELDS",&tfields,card,status);
*status = fits_read_key_lng(outfptr,"TFIELDS",&newTfields,card,status);
for(i = 1; i <= tfields; ++i)
{
snprintf(keyword,FLEN_KEYWORD,"TTYPE%d",i);
*status = fits_read_key_str(infptr,keyword,keyvalue,card,status);
if(*status == KEY_NO_EXIST)
{
*status = 0;
keyvalue[0] = 0;
}
prepare_keyvalue(keyvalue);
if(fits_strcasecmp(keyvalue,"MEMBER_XTENSION") != 0 &&
fits_strcasecmp(keyvalue,"MEMBER_NAME") != 0 &&
fits_strcasecmp(keyvalue,"MEMBER_VERSION") != 0 &&
fits_strcasecmp(keyvalue,"MEMBER_POSITION") != 0 &&
fits_strcasecmp(keyvalue,"MEMBER_LOCATION") != 0 &&
fits_strcasecmp(keyvalue,"MEMBER_URI_TYPE") != 0 )
{
*status = fits_copy_col(infptr,outfptr,i,newTfields+1,1,status);
++newTfields;
}
}
}while(0);
if(mfptr != NULL)
{
fits_close_file(mfptr,status);
}
return(*status);
}
int fftsad(fitsfile *mfptr,
HDUtracker *HDU,
int *newPosition,
char *newFileName)
{
int i;
int hdunum;
int status = 0;
char filename1[FLEN_FILENAME];
char filename2[FLEN_FILENAME];
do
{
fits_get_hdu_num(mfptr,&hdunum);
status = fits_file_name(mfptr,filename1,&status);
status = ffrtnm(filename1,filename2,&status);
for(i = 0;
i < HDU->nHDU && !(HDU->position[i] == hdunum
&& strcmp(HDU->filename[i],filename2) == 0);
++i);
if(i != HDU->nHDU)
{
status = HDU_ALREADY_TRACKED;
if(newPosition != NULL) *newPosition = HDU->newPosition[i];
if(newFileName != NULL) strcpy(newFileName,HDU->newFilename[i]);
continue;
}
if(HDU->nHDU == MAX_HDU_TRACKER)
{
status = TOO_MANY_HDUS_TRACKED;
continue;
}
HDU->filename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char));
if(HDU->filename[i] == NULL)
{
status = MEMORY_ALLOCATION;
continue;
}
HDU->newFilename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char));
if(HDU->newFilename[i] == NULL)
{
status = MEMORY_ALLOCATION;
free(HDU->filename[i]);
continue;
}
HDU->position[i] = hdunum;
HDU->newPosition[i] = hdunum;
strcpy(HDU->filename[i],filename2);
strcpy(HDU->newFilename[i],filename2);
++(HDU->nHDU);
}while(0);
return(status);
}
int fftsud(fitsfile *mfptr,
HDUtracker *HDU,
int newPosition,
char *newFileName)
{
int i;
int hdunum;
int status = 0;
char filename1[FLEN_FILENAME];
char filename2[FLEN_FILENAME];
fits_get_hdu_num(mfptr,&hdunum);
status = fits_file_name(mfptr,filename1,&status);
status = ffrtnm(filename1,filename2,&status);
for(i = 0; i < HDU->nHDU &&
!(HDU->position[i] == hdunum && strcmp(HDU->filename[i],filename2) == 0);
++i);
if(i != HDU->nHDU)
{
if(newPosition != 0) HDU->newPosition[i] = newPosition;
if(newFileName != NULL)
{
strcpy(HDU->newFilename[i],newFileName);
}
}
else
status = MEMBER_NOT_FOUND;
return(status);
}
void prepare_keyvalue(char *keyvalue)
{
int i;
int length;
length = strlen(keyvalue) - 1;
if(keyvalue[0] == '\'' && keyvalue[length] == '\'')
{
for(i = 0; i < length - 1; ++i) keyvalue[i] = keyvalue[i+1];
keyvalue[length-1] = 0;
}
length = strlen(keyvalue) - 1;
for(i = 0; i < length && keyvalue[i] == ' '; ++i);
if(i != length)
{
for(i = length; i >= 0 && keyvalue[i] == ' '; --i) keyvalue[i] = '\0';
}
}
int fits_path2url(char *inpath,
int maxlength,
char *outpath,
int *status)
{
char buff[FLEN_FILENAME];
#if defined(WINNT) || defined(__WINNT__)
if(*status > 0) return(*status);
if(inpath[0] == '/')
{
strcpy(buff,inpath+1);
}
else
{
strcpy(buff,inpath);
}
#elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
int i,j,k;
int size;
if(*status > 0) return(*status);
for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0;
i < size; j = strlen(buff))
{
switch(inpath[i])
{
case ':':
for(k = j; k >= 0; --k) buff[k+1] = buff[k];
buff[0] = '/';
strcat(buff,"/");
++i;
break;
case '\\':
if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/')
{
buff[j] = '/';
buff[j+1] = 0;
}
++i;
break;
default:
buff[j] = inpath[i];
buff[j+1] = 0;
++i;
break;
}
}
#elif defined(VMS) || defined(vms) || defined(__vms)
int i,j,k;
int done;
int size;
if(*status > 0) return(*status);
if(strchr(inpath,']') == NULL)
done = 1;
else
done = 0;
for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0;
i < size && j < FLEN_FILENAME - 8; j = strlen(buff))
{
switch(inpath[i])
{
case ':':
if(inpath[i+1] == ':')
{
for(k = j; k >= 0; --k) buff[k+7] = buff[k];
strncpy(buff,"FILE://",7);
i += 2;
}
else if(strstr(buff,"FILE://") == NULL)
{
for(k = j; k >= 0; --k) buff[k+1] = buff[k];
buff[0] = '/';
++i;
}
else
++i;
strcat(buff,"/");
break;
case ']':
done = 1;
buff[j] = '/';
buff[j+1] = 0;
++i;
break;
case '[':
if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/')
{
buff[j] = '/';
buff[j+1] = 0;
}
++i;
break;
case '.':
if(!done)
{
if(inpath[i-1] == '[')
{
strcat(buff,"./");
++j;
}
else
buff[j] = '/';
}
else
buff[j] = '.';
buff[j+1] = 0;
++i;
break;
case '-':
if(!done)
strcat(buff,"..");
else
{
buff[j] = '-';
buff[j+1] = 0;
}
++i;
break;
default:
buff[j] = inpath[i];
buff[j+1] = 0;
++i;
break;
}
}
if(j > FLEN_FILENAME - 8)
{
*status = URL_PARSE_ERROR;
ffpmsg("resulting path to URL conversion too big (fits_path2url)");
}
#elif defined(macintosh)
int i,j,k;
int firstColon;
int size;
if(*status > 0) return(*status);
for(i = 0, j = 0, firstColon = 1, size = strlen(inpath), buff[0] = 0;
i < size; j = strlen(buff))
{
switch(inpath[i])
{
case ':':
if(firstColon)
{
firstColon = 0;
for(k = j; k >= 0; --k) buff[k+1] = buff[k];
buff[0] = '/';
}
strcat(buff,"/");
++i;
break;
default:
buff[j] = inpath[i];
buff[j+1] = 0;
++i;
break;
}
}
#else
int ii = 0;
int jj = 0;
if(*status > 0) return(*status);
while (inpath[ii]) {
if (inpath[ii] == '/' && inpath[ii+1] == '/') {
} else {
buff[jj] = inpath[ii];
jj++;
}
ii++;
}
buff[jj] = '\0';
#endif
*status = fits_encode_url(buff,maxlength,outpath,status);
return(*status);
}
int fits_url2path(char *inpath,
char *outpath,
int *status)
{
char buff[FLEN_FILENAME];
int absolute;
#if defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
char *tmpStr, *saveptr;
#elif defined(VMS) || defined(vms) || defined(__vms)
int i;
char *tmpStr, *saveptr;
#elif defined(macintosh)
char *tmpStr, *saveptr;
#endif
if(*status != 0) return(*status);
strcpy(buff,inpath);
*status = fits_unencode_url(inpath,buff,status);
if(buff[0] == '/')
absolute = 1;
else
absolute = 0;
#if defined(WINNT) || defined(__WINNT__)
if(absolute)
{
strcpy(outpath,"/");
strcat(outpath,buff);
}
else
{
strcpy(outpath,buff);
}
#elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
{
strcat(outpath,tmpStr);
if(absolute)
{
strcat(outpath,":\\");
absolute = 0;
}
else
strcat(outpath,"\\");
}
outpath[strlen(outpath)-1] = 0;
#elif defined(VMS) || defined(vms) || defined(__vms)
for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
{
if(fits_strcasecmp(tmpStr,"FILE:") == 0)
{
tmpStr = ffstrtok(NULL,"/",&saveptr);
if(tmpStr == NULL) continue;
strcat(outpath,tmpStr);
strcat(outpath,"::");
absolute = 1;
}
else if(strcmp(tmpStr,"..") == 0)
{
if(strlen(outpath) == 0) strcat(outpath,"[");
strcat(outpath,"-.");
}
else if(strcmp(tmpStr,".") == 0 && strlen(outpath) == 0)
{
strcat(outpath,"[.");
}
else if(strchr(tmpStr,'.') != NULL)
{
i = strlen(outpath);
if(i > 0 && outpath[i-1] == '.') outpath[i-1] = ']';
strcat(outpath,tmpStr);
}
else
{
if(absolute)
{
absolute = 0;
strcat(outpath,tmpStr);
strcat(outpath,":[");
}
else if(strlen(outpath) == 0)
{
strcat(outpath,"[");
strcat(outpath,tmpStr);
strcat(outpath,".");
}
else
{
strcat(outpath,tmpStr);
strcat(outpath,".");
}
}
}
#elif defined(macintosh)
for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
{
strcat(outpath,tmpStr);
strcat(outpath,":");
}
outpath[strlen(outpath)-1] = 0;
#else
strcpy(outpath,buff);
#endif
return(*status);
}
int fits_get_cwd(char *cwd,
int *status)
{
char buff[FLEN_FILENAME];
if(*status != 0) return(*status);
#if defined(macintosh)
*buff = 0;
#else
if (!getcwd(buff,FLEN_FILENAME))
{
cwd[0]=0;
ffpmsg("Path and file name too long (fits_get_cwd)");
return (*status=URL_PARSE_ERROR);
}
#endif
fits_path2url(buff,FLEN_FILENAME,cwd,status);
return(*status);
}
int fits_get_url(fitsfile *fptr,
char *realURL,
char *startURL,
char *realAccess,
char *startAccess,
int *iostate,
int *status)
{
int i;
int tmpIOstate = 0;
char infile[FLEN_FILENAME];
char outfile[FLEN_FILENAME];
char tmpStr1[FLEN_FILENAME];
char tmpStr2[FLEN_FILENAME];
char tmpStr3[FLEN_FILENAME];
char tmpStr4[FLEN_FILENAME];
char *tmpPtr;
if(*status != 0) return(*status);
do
{
*tmpStr1 = *tmpStr2 = *tmpStr3 = *tmpStr4 = 0;
*status = fits_file_name(fptr,tmpStr1,status);
*status = ffiurl(tmpStr1,NULL,infile,outfile,NULL,tmpStr2,tmpStr3,
tmpStr4,status);
if((*tmpStr2) || (*tmpStr3) || (*tmpStr4)) tmpIOstate = -1;
*status = ffurlt(fptr,tmpStr3,status);
strcpy(tmpStr4,tmpStr3);
*status = ffrtnm(tmpStr1,tmpStr2,status);
strcpy(tmpStr1,tmpStr2);
if(fits_strcasecmp(tmpStr3,"file://") == 0)
{
tmpIOstate = 1;
if(strlen(outfile)) strcpy(tmpStr1,outfile);
else *tmpStr2 = 0;
if((tmpPtr = strstr(tmpStr1,"://")) != NULL)
{
strcpy(infile,tmpPtr+3);
strcpy(tmpStr1,infile);
}
if((tmpPtr = strstr(tmpStr2,"://")) != NULL)
{
strcpy(infile,tmpPtr+3);
strcpy(tmpStr2,infile);
}
}
else if(fits_strcasecmp(tmpStr3,"mem://") == 0)
{
if(tmpIOstate < 0)
{
ffpmsg("cannot make URL from temp MEM:// file (fits_get_url)");
*status = URL_PARSE_ERROR;
}
else
{
tmpIOstate = 1;
*tmpStr2 = 0;
}
}
else if(fits_strcasecmp(tmpStr3,"memkeep://") == 0)
{
strcpy(tmpStr3,"mem://");
*tmpStr4 = 0;
*tmpStr2 = 0;
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"shmem://") == 0)
{
*tmpStr4 = 0;
*tmpStr2 = 0;
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"root://") == 0)
{
*tmpStr4 = 0;
*tmpStr2 = 0;
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"compressfile://") == 0)
{
strcpy(tmpStr1,outfile);
strcpy(tmpStr2,infile);
strcpy(tmpStr3,"file://");
strcpy(tmpStr4,"file://");
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"httpfile://") == 0)
{
strcpy(tmpStr1,outfile);
strcpy(tmpStr3,"file://");
strcpy(tmpStr4,"http://");
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"ftpfile://") == 0)
{
strcpy(tmpStr1,outfile);
strcpy(tmpStr3,"file://");
strcpy(tmpStr4,"ftp://");
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"stdinfile://") == 0)
{
strcpy(tmpStr1,outfile);
strcpy(tmpStr3,"file://");
strcpy(tmpStr4,"stdin://");
tmpIOstate = 1;
}
else if(fits_strcasecmp(tmpStr3,"compress://") == 0)
{
*tmpStr1 = 0;
strcpy(tmpStr2,infile);
strcpy(tmpStr3,"mem://");
strcpy(tmpStr4,"file://");
tmpIOstate = 0;
}
else if(fits_strcasecmp(tmpStr3,"http://") == 0)
{
*tmpStr1 = 0;
strcpy(tmpStr3,"mem://");
strcpy(tmpStr4,"http://");
tmpIOstate = 0;
}
else if(fits_strcasecmp(tmpStr3,"httpcompress://") == 0)
{
*tmpStr1 = 0;
strcpy(tmpStr3,"mem://");
strcpy(tmpStr4,"http://");
tmpIOstate = 0;
}
else if(fits_strcasecmp(tmpStr3,"ftp://") == 0)
{
*tmpStr1 = 0;
strcpy(tmpStr3,"mem://");
strcpy(tmpStr4,"ftp://");
tmpIOstate = 0;
}
else if(fits_strcasecmp(tmpStr3,"ftpcompress://") == 0)
{
*tmpStr1 = 0;
strcpy(tmpStr3,"mem://");
strcpy(tmpStr4,"ftp://");
tmpIOstate = 0;
}
else if(fits_strcasecmp(tmpStr3,"stdin://") == 0)
{
*status = URL_PARSE_ERROR;
ffpmsg("cannot make valid URL from stdin:// (fits_get_url)");
*tmpStr1 = *tmpStr2 = 0;
}
else if(fits_strcasecmp(tmpStr3,"stdout://") == 0)
{
*status = URL_PARSE_ERROR;
ffpmsg("cannot make valid URL from stdout:// (fits_get_url)");
*tmpStr1 = *tmpStr2 = 0;
}
else if(fits_strcasecmp(tmpStr3,"irafmem://") == 0)
{
*status = URL_PARSE_ERROR;
ffpmsg("cannot make valid URL from irafmem:// (fits_get_url)");
*tmpStr1 = *tmpStr2 = 0;
}
if(*status != 0) continue;
if(realURL != NULL)
{
if(strlen(tmpStr1) == 0)
*realURL = 0;
else
{
if((tmpPtr = strstr(tmpStr1,"://")) != NULL)
{
tmpPtr += 3;
i = (long)tmpPtr - (long)tmpStr1;
strncpy(realURL,tmpStr1,i);
}
else
{
tmpPtr = tmpStr1;
i = 0;
}
*status = fits_path2url(tmpPtr,FLEN_FILENAME-i,realURL+i,status);
}
}
if(startURL != NULL)
{
if(strlen(tmpStr2) == 0)
*startURL = 0;
else
{
if((tmpPtr = strstr(tmpStr2,"://")) != NULL)
{
tmpPtr += 3;
i = (long)tmpPtr - (long)tmpStr2;
strncpy(startURL,tmpStr2,i);
}
else
{
tmpPtr = tmpStr2;
i = 0;
}
*status = fits_path2url(tmpPtr,FLEN_FILENAME-i,startURL+i,status);
}
}
if(realAccess != NULL) strcpy(realAccess,tmpStr3);
if(startAccess != NULL) strcpy(startAccess,tmpStr4);
if(iostate != NULL) *iostate = tmpIOstate;
}while(0);
return(*status);
}
typedef char* grp_stack_data;
typedef struct grp_stack_item_struct {
grp_stack_data data;
struct grp_stack_item_struct* next;
struct grp_stack_item_struct* prev;
} grp_stack_item;
typedef struct grp_stack_struct {
size_t stack_size;
grp_stack_item* top;
} grp_stack;
static char* grp_stack_default = NULL;
static void delete_grp_stack(grp_stack** mystack);
static grp_stack_item* grp_stack_append(
grp_stack_item* last, grp_stack_data data
);
static grp_stack_data grp_stack_remove(grp_stack_item* last);
static grp_stack* new_grp_stack(void);
static grp_stack_data pop_grp_stack(grp_stack* mystack);
static void push_grp_stack(grp_stack* mystack, grp_stack_data data);
static grp_stack_data shift_grp_stack(grp_stack* mystack);
int fits_clean_url(char *inURL,
char *outURL,
int *status)
{
grp_stack* mystack;
char* tmp;
char *saveptr;
if(*status) return *status;
mystack = new_grp_stack();
*outURL = 0;
do {
tmp = strstr(inURL, "://");
if(tmp) {
tmp = strchr(tmp + 3, '/');
if(tmp) {
size_t string_size = (size_t) (tmp - inURL);
strncpy(outURL, inURL, string_size);
outURL[string_size] = 0;
inURL = tmp;
} else {
strcpy(outURL, inURL);
continue;
}
}
if('/' == *inURL) strcat(outURL, "/");
tmp = ffstrtok(inURL, "/",&saveptr);
while(tmp) {
if(!strcmp(tmp, "..")) {
if(0 < mystack->stack_size) pop_grp_stack(mystack);
else if('/' != *inURL) push_grp_stack(mystack, tmp);
} else {
if(strcmp(tmp, ".")) push_grp_stack(mystack, tmp);
}
tmp = ffstrtok(NULL, "/",&saveptr);
}
while(0 < mystack->stack_size) {
tmp = shift_grp_stack(mystack);
if (strlen(outURL) + strlen(tmp) + 1 > FLEN_FILENAME-1)
{
outURL[0]=0;
ffpmsg("outURL is too long (fits_clean_url)");
*status = URL_PARSE_ERROR;
delete_grp_stack(&mystack);
return *status;
}
strcat(outURL, tmp);
strcat(outURL, "/");
}
outURL[strlen(outURL) - 1] = 0;
} while(0);
delete_grp_stack(&mystack);
return *status;
}
static void delete_grp_stack(grp_stack** mystack) {
if(!mystack || !*mystack) return;
while((*mystack)->stack_size) pop_grp_stack(*mystack);
free(*mystack);
*mystack = NULL;
}
static grp_stack_item* grp_stack_append(
grp_stack_item* last, grp_stack_data data
) {
grp_stack_item* new_item = (grp_stack_item*) malloc(sizeof(grp_stack_item));
new_item->data = data;
if(last) {
new_item->next = last->next;
new_item->prev = last;
last->next->prev = new_item;
last->next = new_item;
} else {
new_item->next = new_item;
new_item->prev = new_item;
}
return new_item;
}
static grp_stack_data grp_stack_remove(grp_stack_item* last) {
grp_stack_data retval = last->data;
last->prev->next = last->next;
last->next->prev = last->prev;
free(last);
return retval;
}
static grp_stack* new_grp_stack(void) {
grp_stack* retval = (grp_stack*) malloc(sizeof(grp_stack));
if(retval) {
retval->stack_size = 0;
retval->top = NULL;
}
return retval;
}
static grp_stack_data pop_grp_stack(grp_stack* mystack) {
grp_stack_data retval = grp_stack_default;
if(mystack && mystack->top) {
grp_stack_item* newtop = mystack->top->prev;
retval = grp_stack_remove(mystack->top);
mystack->top = newtop;
if(0 == --mystack->stack_size) mystack->top = NULL;
}
return retval;
}
static void push_grp_stack(grp_stack* mystack, grp_stack_data data) {
if(!mystack) return;
mystack->top = grp_stack_append(mystack->top, data);
++mystack->stack_size;
return;
}
static grp_stack_data shift_grp_stack(grp_stack* mystack) {
grp_stack_data retval = grp_stack_default;
if(mystack && mystack->top) {
retval = grp_stack_remove(mystack->top->next);
if(0 == --mystack->stack_size) mystack->top = NULL;
}
return retval;
}
int fits_url2relurl(char *refURL,
char *absURL,
char *relURL,
int *status)
{
int i,j;
int refcount,abscount;
int refsize,abssize;
int done;
if(*status != 0) return(*status);
relURL[0] = 0;
do
{
if(!(fits_is_url_absolute(refURL) || *refURL == '/') ||
!(fits_is_url_absolute(absURL) || *absURL == '/'))
{
*status = URL_PARSE_ERROR;
ffpmsg("Cannot make rel. URL from non abs. URLs (fits_url2relurl)");
continue;
}
refsize = strlen(refURL);
abssize = strlen(absURL);
for(done = 0, refcount = 0, abscount = 0;
!done && refcount < refsize && abscount < abssize;
++refcount, ++abscount)
{
for(; abscount < abssize && absURL[abscount] == '/'; ++abscount);
for(; refcount < refsize && refURL[refcount] == '/'; ++refcount);
for(i = abscount; absURL[i] != '/' && i < abssize; ++i);
for(j = refcount; refURL[j] != '/' && j < refsize; ++j);
if(i == j &&
strncmp(absURL+abscount, refURL+refcount,i-refcount) == 0)
{
abscount = i; refcount = j;
continue;
}
for(j = refcount; j < refsize; ++j)
if(refURL[j] == '/')
{
if (strlen(relURL)+3 > FLEN_FILENAME-1)
{
*status = URL_PARSE_ERROR;
ffpmsg("relURL too long (fits_url2relurl)");
return (*status);
}
strcat(relURL,"../");
}
if (strlen(relURL) + strlen(absURL+abscount) > FLEN_FILENAME-1)
{
*status = URL_PARSE_ERROR;
ffpmsg("relURL too long (fits_url2relurl)");
return (*status);
}
strcat(relURL,absURL+abscount);
done = 1;
}
}while(0);
return(*status);
}
int fits_relurl2url(char *refURL,
char *relURL,
char *absURL,
int *status)
{
int i;
char tmpStr[FLEN_FILENAME];
char *tmpStr1, *tmpStr2;
if(*status != 0) return(*status);
do
{
if (strlen(refURL) > FLEN_FILENAME-1)
{
absURL[0]=0;
ffpmsg("ref URL is too long (fits_relurl2url)");
*status = URL_PARSE_ERROR;
continue;
}
strcpy(tmpStr,refURL);
if(fits_strncasecmp(tmpStr,"MEM:",4) == 0 ||
fits_strncasecmp(tmpStr,"SHMEM:",6) == 0)
{
ffpmsg("ref URL has access mem:// or shmem:// (fits_relurl2url)");
ffpmsg(" cannot construct full URL from a partial URL and ");
ffpmsg(" MEM/SHMEM base URL");
*status = URL_PARSE_ERROR;
continue;
}
if(relURL[0] != '/')
{
tmpStr1 = strrchr(tmpStr,'/');
if(tmpStr1 != NULL) tmpStr1[1] = 0;
else tmpStr[0] = 0;
if (strlen(tmpStr)+strlen(relURL) > FLEN_FILENAME-1)
{
absURL[0]=0;
ffpmsg("rel + ref URL is too long (fits_relurl2url)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(tmpStr,relURL);
}
else
{
strcpy(absURL,"/");
for(i = 0; relURL[i] == '/'; ++i)
{
if (strlen(absURL) + 1 > FLEN_FILENAME-1)
{
absURL[0]=0;
ffpmsg("abs URL is too long (fits_relurl2url)");
*status = URL_PARSE_ERROR;
return (*status);
}
strcat(absURL,"/");
}
for(tmpStr1 = tmpStr, i = strlen(absURL);
(tmpStr2 = strstr(tmpStr1,absURL)) != NULL;
tmpStr1 = tmpStr2 + i);
absURL[i-1] = 0;
tmpStr2 = strstr(tmpStr1,absURL);
if(tmpStr2 == NULL)
{
tmpStr2 = strrchr(tmpStr1,'/');
if(tmpStr2 != NULL) tmpStr2[0] = 0;
else tmpStr[0] = 0;
}
else
{
*tmpStr2 = 0;
}
if (strlen(tmpStr)+strlen(relURL) > FLEN_FILENAME-1)
{
absURL[0]=0;
ffpmsg("rel + ref URL is too long (fits_relurl2url)");
*status = URL_PARSE_ERROR;
continue;
}
strcat(tmpStr,relURL);
}
*status = fits_clean_url(tmpStr,absURL,status);
}while(0);
return(*status);
}
int fits_encode_url(char *inpath,
int maxlength,
char *outpath,
int *status)
{
unsigned char a;
char *p;
char *q;
char *hex = "0123456789ABCDEF";
int iout=0;
unsigned const char isAcceptable[96] =
{
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0xE,0x0,0xF,0xF,0xC,
0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x8,0x0,0x0,0x0,0x0,0x0,
0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,
0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xF,
0x0,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,
0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0x0
};
if(*status != 0) return(*status);
for(q = outpath, p = inpath; *p && (iout < maxlength-1) ; p++)
{
a = (unsigned char)*p;
if(!( a>=32 && a<128 && (isAcceptable[a-32])))
{
if (iout+2 < maxlength-1)
{
*q++ = HEX_ESCAPE;
*q++ = hex[a >> 4];
*q++ = hex[a & 15];
iout += 3;
}
else
{
ffpmsg("URL input is too long to encode (fits_encode_url)");
*status = URL_PARSE_ERROR;
outpath[0] = 0;
return (*status);
}
}
else
{
*q++ = *p;
iout++;
}
}
if (*p && (iout == maxlength-1))
{
ffpmsg("URL input is too long to encode (fits_encode_url)");
*status = URL_PARSE_ERROR;
outpath[0] = 0;
return (*status);
}
*q++ = 0;
return(*status);
}
int fits_unencode_url(char *inpath,
char *outpath,
int *status)
{
char *p;
char *q;
char c;
if(*status != 0) return(*status);
p = inpath;
q = outpath;
while(*p != 0)
{
if (*p == HEX_ESCAPE)
{
if((c = *(++p)) != 0)
{
*q = (
(c >= '0' && c <= '9') ?
(c - '0') : ((c >= 'A' && c <= 'F') ?
(c - 'A' + 10) : (c - 'a' + 10))
)*16;
if((c = *(++p)) != 0)
{
*q = *q + (
(c >= '0' && c <= '9') ?
(c - '0') : ((c >= 'A' && c <= 'F') ?
(c - 'A' + 10) : (c - 'a' + 10))
);
p++, q++;
}
}
}
else
*q++ = *p++;
}
*q = 0;
return(*status);
}
int fits_is_url_absolute(char *url)
{
char *tmpStr1, *tmpStr2;
char reserved[] = {':',';','/','?','@','&','=','+','$',','};
if( (tmpStr1 = strchr(url,reserved[0])) != NULL &&
((tmpStr2 = strchr(url,reserved[1])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[2])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[3])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[4])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[5])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[6])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[7])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[8])) == NULL || tmpStr2 > tmpStr1) &&
((tmpStr2 = strchr(url,reserved[9])) == NULL || tmpStr2 > tmpStr1) )
{
return(1);
}
else
{
return(0);
}
}