
/*
    LinuxWare daemon - Netware like server for Linux

    Copyright (C) 1994, 1995  Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <netinet/in.h>
#include "bindauth.h"
#include "mangle.h"
#include "util.h"
#include "logging.h"
#include "filesearch.h"

int nw_extract_filename(char* name,char* ext,char* path)
{
	char* q;
	LPRINTF(LL_DEBUG,("extract: %s\n",path));
	if (*path=='.' || *path==0) {LPRINTF(LL_DEBUG,("ext1!\n"));return 0;}
	for(q=name;;path++,q++)
	{
		if (*path==0) {*q=0;ext[1]=0;ext[0]=(*name=='*'?'*':0);return 1;}
		if ((*path&0x7F)=='.') 
		{
			path++;
			*q=0;
			for(q=ext;q<ext+3;path++,q++)
			{
				if (*path==0) {*q=0;return 1;}
				*q=tolower(*path&0x7F);
			}
			if (*path==0) {*q=0;return 1;}
			LPRINTF(LL_DEBUG,("ext2!\n"));
			return 0;
		}
		if (q>=name+8) {LPRINTF(LL_DEBUG,("ext4!\n"));return 0;}
		*q=tolower(*path&0x7F);
	}
	LPRINTF(LL_DEBUG,("ext3!\n"));
	return 0;
}

int strwildequal(char* s,char* t)
{
	LPRINTF(LL_DEBUG,("strwildequal: '%s' '%s'\n",s,t));
	for(;*s && *t;s++,t++)
	{
		if (*t=='*') return 1;
		if (*s!=*t && *t!='?') return 0;
	}
	if (*s==0)
	{
		if (*t==0) return 1;
		for(;*t;t++)
		{
			if (*t!='?' && *t!='*') return 0;
		}
		return 1;
	}
	return 0;
}

int nw_wildcard_match(char* name,char* template)
{
	char n_name[9];
	char n_ext[4];
	char t_name[9];
	char t_ext[4];
	if (strcmp(name,".")==0) return 0;
	if (strcmp(name,"..")==0) return 0;
	LPRINTF(LL_DEBUG,("match\n"));
	if (!nw_extract_filename(n_name,n_ext,name)) return 0;
	LPRINTF(LL_DEBUG,("match2\n"));
	if (!nw_extract_filename(t_name,t_ext,template)) return 0;
	LPRINTF(LL_DEBUG,("match3\n"));
	return strwildequal(n_name,t_name) && strwildequal(n_ext,t_ext); 
}

void ncp_set_filedir_prop(ncp_filedir_prop* prop,struct stat* fs)
{
	if (S_ISDIR(fs->st_mode))
	{
		prop->dir.d_attr=0x10; /* hard wired 0x10 */
		prop->dir.d_acc=0xFF; /* hard wired 0xFF */
		prop->dir.d_creat=htons(time2nw_date(fs->st_mtime));
		prop->dir.t_creat=htons(time2nw_time(fs->st_mtime));
		prop->dir.uid=htonl(fs->st_uid);
		prop->dir.fill=0; /* ???? */
		prop->dir.stamp=0;
	}
	else
	{
		prop->file.f_attr=0x20; /* hard wired 0x20 */
		prop->file.f_mode=0; /* hard wired 0 */
		prop->file.f_size=htonl(fs->st_size);
		prop->file.d_creat=htons(time2nw_date(fs->st_mtime));
		prop->file.d_acc=htons(time2nw_date(fs->st_atime));
		prop->file.d_upd=htons(time2nw_date(fs->st_mtime));
		prop->file.t_upd=htons(time2nw_time(fs->st_mtime));
	}
	return;
}

int nw_file_search(ncp_filename* name,word* new_context,ncp_filedir_prop* prop,
		   dir_handle* dh,char* search_path,char* template,byte attr,word context)
{		  
	char path[MAX_PATH];

	nw2unix_path(path,dh,search_path);
	return nw_file_search_path(name,new_context,prop,path,template,attr,context);
}

int nw_file_search_path(ncp_filename* name,word* new_context,ncp_filedir_prop* prop,
		   char* path,char* template,byte attr,word context)
{
	char entry_path[MAX_PATH];
	DIR* dir;

	dir=opendir(path);
	if (dir!=NULL)
	{
		struct dirent* dent;
		struct stat fs;
		
		LPRINTF(LL_DEBUG,("file search context: %i\n",ntohs(context)));
		if (context!=0xFFFF) seekdir(dir,ntohs(context));
		do
		{
			char mang_name[1000];
			dent=readdir(dir);
			if (dent==NULL) break;
/*			LPRINTF(LL_INFO,("pred mangle\n"));*/
			if (mangle83(mang_name,dent->d_name)==NULL) continue;
/*			LPRINTF(LL_INFO,("po mangle\n"));*/
			if (!nw_wildcard_match(mang_name,template)) continue;
			strcpy(entry_path,path);
			strcat(entry_path,"/");
			strcat(entry_path,dent->d_name);
			*new_context=htons(telldir(dir));
			if (stat(entry_path,&fs)!=0) continue;
			LPRINTF(LL_DEBUG,("stat: %s \n",path));
			if ((S_ISDIR(fs.st_mode)!=0)^((attr&0x10)!=0)) continue;
			memset(name->name,0,sizeof(*name));
			strncpy(name->name,mang_name,sizeof(*name)-1);
			ncp_set_filedir_prop(prop,&fs);
			closedir(dir);
			return 1;
		} while (1);
		closedir(dir);
	}
	return 0;
}


int nw_file_search1(ncp_filename* name,word* new_context,ncp_filedir_prop* prop,
		   dir_handle* dh,char* path,byte attr,word context)
{
	char* p;
	for(p=path+strlen(path);p>=path;p--)
	{
		if (*p=='\\' || *p=='/' || *p==':') break;
	}
	if (*p=='\\' || *p=='/')
	{
		*p=0;
		return nw_file_search(name,new_context,prop,dh,path,p+1,attr,context);
	}
	else
	{
		if (*p==':')
		{
			if (*(p+1)==0)
			{
				/* old *p=0; */
				return nw_file_search(name,new_context,prop,dh,
				  path,"*",attr,context); /* old "",path */
			}
			else
			{
				char vpath[MAX_PATH];
				*p=0;
				strcpy(vpath,path);
				strcat(vpath,":");
				return nw_file_search(name,new_context,prop,dh,
				  vpath,p+1,attr,context);
			}
		}
		else
		{
			/* path=="" ?????????????? */
			return nw_file_search(name,new_context,prop,dh,"",
			  path,attr,context);
		}
	}
}

byte unix2nw_file_rights(int ur,int uw,int ux)
{
	int res=ER_SEARCH|ER_OPEN;
	
	if (ur) res|=ER_READ;
	if (uw) res|=ER_WRITE|ER_DELETE|ER_MODIFY;
	return res;
}

byte unix2nw_dir_rights(int ur,int uw,int ux)
{
	int res=0;
	
	if (ux)
	{
		res=ER_READ|ER_WRITE|ER_OPEN;
		if (ur) res|=ER_SEARCH;
		if (uw) res|=ER_CREATE|ER_DELETE|ER_MODIFY;
	}
	return res;
}

byte unix2nw_rights(int mode,int ouid,int ogid)
{
	int ur,uw,ux,uid,gid;
	
	uid=get_cur_uid();
	gid=get_cur_gid();
	
	if (uid==ouid)
	{
		ur=mode&S_IRUSR;
		uw=mode&S_IWUSR;
		ux=mode&S_IXUSR;
	}
	else
	{
		if (gid==ogid)
		{
			ur=mode&S_IRGRP;
			uw=mode&S_IWGRP;
			ux=mode&S_IXGRP;
		}
		else
		{
			ur=mode&S_IROTH;
			uw=mode&S_IWOTH;
			ux=mode&S_IXOTH;
		}
	}

	if (mode & S_IFDIR) return unix2nw_dir_rights(ur,uw,ux);
	return unix2nw_file_rights(ur,uw,ux);	
}
