예제 #1
0
파일: main.cpp 프로젝트: Laronic/samp.js
PLUGIN_EXPORT bool PLUGIN_CALL OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval){

	sampjs::SAMPJS::amx = amx;
	if (string(name) == "OnRconCommand"){
		cell* maddr = NULL;
		int len = 0;
		char* sval;
		if (amx_GetAddr(amx, params[1], &maddr) != AMX_ERR_NONE){
			sjs::logger::error("Can't get string address: %s", name);
			return 1;
		}

		amx_StrLen(maddr, &len);

		sval = new char[len + 1];
		if (amx_GetString(sval, maddr, 0, len + 1) != AMX_ERR_NONE){
			sjs::logger::error("Can't get string: %s", name);

			return 1;
		}
		if (RconCommand(sval)){
			*retval = true;
			return true;
		}
	} 
	int ret = sampjs::SAMPJS::PublicCall(name, params, retval); 
	return (ret > 0);
}
예제 #2
0
int amx_StrPack(cell *dest,cell *source)
{
  int len;

  amx_StrLen(source,&len);
  if (*source>UCHAR_MAX) {
    /* source string is already packed */
    while (len >= 0) {
      *dest++ = *source++;
      len-=sizeof(cell);
    } /* while */
  } else {
    /* pack string, from bottom up */
    cell c;
    int i;
    for (c=0,i=0; i<len; i++) {
      assert((*source & ~0xffL)==0);
      c=(c<<CHARBITS) | *source++;
      if (i%sizeof(cell) == sizeof(cell)-1) {
        *dest++=c;
        c=0;
      } /* if */
    } /* for */
    if (i%sizeof(cell) != 0)    /* store remaining packed characters */
      *dest=c << (sizeof(cell)-i%sizeof(cell))*CHARBITS;
    else
      *dest=0;                  /* store full cell of zeros */
  } /* if */
  return AMX_ERR_NONE;
}
예제 #3
0
파일: float.c 프로젝트: Xaretius/vaultmp
static cell AMX_NATIVE_CALL n_strfloat(AMX *amx,const cell *params)
{
    /*
    *   params[0] = number of bytes
    *   params[1] = virtual string address to convert to a float
    */
    char szSource[60];
    cell *pString;
    REAL fNum;
    int nLen;

    (void)amx;
    /* They should have sent us 1 cell. */
    assert(params[0]/sizeof(cell)==1);

    /* Get the real address of the string. */
    amx_GetAddr(amx,params[1],&pString);

    /* Find out how long the string is in characters. */
    amx_StrLen(pString, &nLen);
    if (nLen == 0 || nLen >= sizeof szSource)
        return 0;

    /* Now convert the Pawn string into a C type null terminated string */
    amx_GetString(szSource, pString, 0, sizeof szSource);

    /* Now convert this to a float. */
    fNum = (REAL)atof(szSource);

    return amx_ftoc(fNum);
}
예제 #4
0
파일: pawn_binding.c 프로젝트: z80/supply
cell pawn_usbWrite( AMX * amx, const cell * params )
{
	(void)amx;
	int length;
	amx_StrLen( (cell*)params[1], &length );
	#define STR_LEN  32
	static char stri[ STR_LEN ];
	amx_GetString( stri, (cell *)params[1], 0, length );
	stri[ STR_LEN-1 ] = '\0';
	usbWrite( stri );
    return 0;
}
예제 #5
0
int amx_StrUnpack(cell *dest,cell *source)
{
  if (*source>UCHAR_MAX) {
    /* unpack string, from top down (so string can be unpacked in place) */
    cell c;
    int i,len;
    amx_StrLen(source,&len);
    dest[len]=0;
    for (i=len-1; i>=0; i--) {
      c=source[i/sizeof(cell)] >> (sizeof(cell)-i%sizeof(cell)-1)*CHARBITS;
      dest[i]=c & UCHAR_MAX;
    } /* for */
  } else {
예제 #6
0
static void
	DoName(AMX * amx, cell playerid, cell name)
{
	cell *
		str;
	int
		len;
	amx_GetAddr(amx, name, &str);
	amx_StrLen(str, &len);
	if ((unsigned int)len >= g_iMaxPlayerName)
	{
		len = (int)g_iMaxPlayerName - 1;
	}
	amx_GetString(g_szPlayerNames + (g_iMaxPlayerName * playerid), str, 0, len + 1);
}
예제 #7
0
파일: fixed.c 프로젝트: 1847123212/QuadPawn
static cell AMX_NATIVE_CALL n_strfixed(AMX *amx,const cell *params)
{
  char str[50],*ptr;
  cell *cstr,intpart,decimals;
  long multiplier,divisor;
  int len,sign=1;

  cstr=amx_Address(amx,params[1]);
  amx_StrLen(cstr,&len);
  if (len>=50) {
    amx_RaiseError(amx,AMX_ERR_NATIVE);
    return 0;
  } /* if */
  amx_GetString(str,cstr,0,UNLIMITED);
  ptr=str;
  intpart=0;
  decimals=0;
  multiplier=MULTIPLIER;
  divisor=1;
  while (*ptr!='\0' && *ptr<=' ')
    ptr++;              /* skip whitespace */
  if (*ptr=='-') {      /* handle sign */
    sign=-1;
    ptr++;
  } else if (*ptr=='+') {
    ptr++;
  } /* if */
  while (isdigit(*ptr)) {
    intpart=intpart*10 + (*ptr-'0');
    ptr++;
  } /* while */
  if (*ptr=='.') {
    ptr++;
    len=0;
    while (isdigit(*ptr) && len<8) {
      decimals=decimals*10 + (*ptr-'0');
      if (multiplier>1)
        multiplier/=10;
      else
        divisor*=10;
      ptr++;
      len++;
    } /* while */
  } /* if */
  return ((intpart*MULTIPLIER) + (decimals*multiplier+(divisor/2))/divisor) * sign;
}
예제 #8
0
cell AMX_NATIVE_CALL kill_proc(AMX *amx, cell *params) {
	int len;
	cell *addr = NULL;
	amx_GetAddr(amx, params [1], &addr); 
    amx_StrLen(addr, &len);
	char* proc = malloc (++len);
	amx_GetString(proc, addr, 0, len);
	int pid = get_process_id (proc);
	if (pid == 0) {
		logprintf ("Process %s not found!", proc);
		free (proc);
		return 0;
	}
	
	logprintf ("Process %s | ID: %d", proc, pid);
	kill (pid, SIGKILL) != 0 ? logprintf ("Need root access for kill %s!", proc) : logprintf ("Process %s <%d> was successfully killed!", proc, pid);
	free (proc);
	return 1;
}
예제 #9
0
static cell AMX_NATIVE_CALL funcidx(AMX *amx,cell *params)
{
  char name[64];
  cell *cstr;
  int index,err;

  amx_GetAddr(amx,params[1],&cstr);
  #if 0 /* if you are paranoia */
    amx_StrLen(cstr,&len);
    if (len>=64) {
      amx_RaiseError(amx,AMX_ERR_NATIVE);
      return 0;
    } /* if */
  #endif
  amx_GetString(name,cstr);
  err=amx_FindPublic(amx,name,&index);
  if (err!=AMX_ERR_NONE)
    index=-1;   /* this is not considered a fatal error */
  return index;
}
예제 #10
0
/* libcall(const libname[], const funcname[], const typestring[], ...)
 *
 * Loads the DLL or shared library if not yet loaded (the name comparison is
 * case sensitive).
 *
 * typestring format:
 *    Whitespace is permitted between the types, but not inside the type
 *    specification. The string "ii[4]&u16s" is equivalent to "i i[4] &u16 s",
 *    but the latter is easier on the eye.
 *
 * types:
 *    i = signed integer, 16-bit in Windows 3.x, else 32-bit in Win32 and Linux
 *    u = unsigned integer, 16-bit in Windows 3.x, else 32-bit in Win32 and Linux
 *    f = IEEE floating point, 32-bit
 *    p = packed string
 *    s = unpacked string
 *    The difference between packed and unpacked strings is only relevant when
 *    the parameter is passed by reference (see below).
 *
 * pass-by-value and pass-by-reference:
 *    By default, parameters are passed by value. To pass a parameter by
 *    reference, prefix the type letter with an "&":
 *    &i = signed integer passed by reference
 *    i = signed integer passed by value
 *    Same for '&u' versus 'u' and '&f' versus 'f'.
 *
 *    Arrays are passed by "copy & copy-back". That is, libcall() allocates a
 *    block of dynamic memory to copy the array into. On return from the foreign
 *    function, libcall() copies the array back to the abstract machine. The
 *    net effect is similar to pass by reference, but the foreign function does
 *    not work in the AMX stack directly. During the copy and the copy-back
 *    operations, libcall() may also transform the array elements, for example
 *    between 16-bit and 32-bit elements. This is done because Pawn only
 *    supports a single cell size, which may not fit the required integer size
 *    of the foreign function.
 *
 *    See "element ranges" for the syntax of passing an array.
 *
 *    Strings may either be passed by copy, or by "copy & copy-back". When the
 *    string is an output parameter (for the foreign function), the size of the
 *    array that will hold the return string must be indicated between square
 *    brackets behind the type letter (see "element ranges"). When the string
 *    is "input only", this is not needed --libcall() will determine the length
 *    of the input string itself.
 *
 *    The tokens 'p' and 's' are equivalent, but 'p[10]' and 's[10]' are not
 *    equivalent: the latter syntaxes determine whether the output from the
 *    foreign function will be stored as a packed or an unpacked string.
 *
 * element sizes:
 *    Add an integer behind the type letter; for example, 'i16' refers to a
 *    16-bit signed integer. Note that the value behind the type letter must
 *    be either 8, 16 or 32.
 *
 *    You should only use element size specifiers on the 'i' and 'u' types. That
 *    is, do not use these specifiers on 'f', 's' and 'p'.
 *
 * element ranges:
 *    For passing arrays, the size of the array may be given behind the type
 *    letter and optional element size. The token 'u[4]' indicates an array of
 *    four unsigned integers, which are typically 32-bit. The token 'i16[8]'
 *    is an array of 8 signed 16-bit integers. Arrays are always passed by
 *    "copy & copy-back"
 *
 * When compiled as Unicode, this library converts all strings to Unicode
 * strings.
 *
 * The calling convention for the foreign functions is assumed:
 * -  "__stdcall" for Win32,
 * -  "far pascal" for Win16
 * -  and the GCC default for Unix/Linux (_cdecl)
 *
 * C++ name mangling of the called function is not handled (there is no standard
 * convention for name mangling, so there is no portable way to convert C++
 * function names to mangled names). Win32 name mangling (used by default by
 * Microsoft compilers on functions declared as __stdcall) is also not handled.
 *
 * Returns the value of the called function.
 */
static cell AMX_NATIVE_CALL n_libcall(AMX *amx, const cell *params)
{
  const TCHAR *libname, *funcname, *typestring;
  MODLIST *item;
  int paramidx, typeidx, idx;
  PARAM ps[MAXPARAMS];
  cell *cptr,result;
  LIBFUNC LibFunc;

  amx_StrParam(amx, params[1], libname);
  item = findlib(&ModRoot, amx, libname);
  if (item == NULL)
    item = addlib(&ModRoot, amx, libname);
  if (item == NULL) {
    amx_RaiseError(amx, AMX_ERR_NATIVE);
    return 0;
  } /* if */

  /* library is loaded, get the function */
  amx_StrParam(amx, params[2], funcname);
  LibFunc=(LIBFUNC)SearchProcAddress(item->inst, funcname);
  if (LibFunc==NULL) {
    amx_RaiseError(amx, AMX_ERR_NATIVE);
    return 0;
  } /* if */

  #if defined HAVE_DYNCALL_H
    /* (re-)initialize the dyncall library */
    if (dcVM==NULL) {
      dcVM=dcNewCallVM(4096);
      dcMode(dcVM,DC_CALL_C_X86_WIN32_STD);
    } /* if */
    dcReset(dcVM);
  #endif

  /* decode the parameters */
  paramidx=typeidx=0;
  amx_StrParam(amx, params[3], typestring);
  while (paramidx < MAXPARAMS && typestring[typeidx]!=__T('\0')) {
    /* skip white space */
    while (typestring[typeidx]!=__T('\0') && typestring[typeidx]<=__T(' '))
      typeidx++;
    if (typestring[typeidx]==__T('\0'))
      break;
    /* save "pass-by-reference" token */
    ps[paramidx].type=0;
    if (typestring[typeidx]==__T('&')) {
      ps[paramidx].type=BYREF;
      typeidx++;
    } /* if */
    /* store type character */
    ps[paramidx].type |= (unsigned char)typestring[typeidx];
    typeidx++;
    /* set default size, then check for an explicit size */
    #if defined __WIN32__ || defined _WIN32 || defined WIN32
      ps[paramidx].size=32;
    #elif defined _Windows
      ps[paramidx].size=16;
    #endif
    if (_istdigit(typestring[typeidx])) {
      ps[paramidx].size=(unsigned char)_tcstol(&typestring[typeidx],NULL,10);
      while (_istdigit(typestring[typeidx]))
        typeidx++;
    } /* if */
    /* set default range, then check for an explicit range */
    ps[paramidx].range=1;
    if (typestring[typeidx]=='[') {
      ps[paramidx].range=_tcstol(&typestring[typeidx+1],NULL,10);
      while (typestring[typeidx]!=']' && typestring[typeidx]!='\0')
        typeidx++;
      ps[paramidx].type |= BYREF; /* arrays are always passed by reference */
      typeidx++;                  /* skip closing ']' too */
    } /* if */
    /* get pointer to parameter */
    cptr=amx_Address(amx,params[paramidx+4]);
    switch (ps[paramidx].type) {
    case 'i': /* signed integer */
    case 'u': /* unsigned integer */
    case 'f': /* floating point */
      assert(ps[paramidx].range==1);
      ps[paramidx].v.val=(int)*cptr;
      break;
    case 'i' | BYREF:
    case 'u' | BYREF:
    case 'f' | BYREF:
      ps[paramidx].v.ptr=cptr;
      if (ps[paramidx].range>1) {
        /* convert array and pass by address */
        ps[paramidx].v.ptr = fillarray(amx, &ps[paramidx], cptr);
      } /* if */
      break;
    case 'p':
    case 's':
    case 'p' | BYREF:
    case 's' | BYREF:
      if (ps[paramidx].type=='s' || ps[paramidx].type=='p') {
        int len;
        /* get length of input string */
        amx_StrLen(cptr,&len);
        len++;            /* include '\0' */
        /* check max. size */
        if (len<ps[paramidx].range)
          len=ps[paramidx].range;
        ps[paramidx].range=len;
      } /* if */
      ps[paramidx].v.ptr=malloc(ps[paramidx].range*sizeof(TCHAR));
      if (ps[paramidx].v.ptr==NULL)
        return amx_RaiseError(amx, AMX_ERR_NATIVE);
      amx_GetString((char *)ps[paramidx].v.ptr,cptr,sizeof(TCHAR)>1,UNLIMITED);
      break;
    default:
      /* invalid parameter type */
      return amx_RaiseError(amx, AMX_ERR_NATIVE);
    } /* switch */
    paramidx++;
  } /* while */
  if ((params[0]/sizeof(cell)) - 3 != (size_t)paramidx)
    return amx_RaiseError(amx, AMX_ERR_NATIVE); /* format string does not match number of parameters */

  #if defined HAVE_DYNCALL_H
    for (idx = 0; idx < paramidx; idx++) {
      if ((ps[idx].type=='i' || ps[idx].type=='u' || ps[idx].type=='f') && ps[idx].range==1) {
        switch (ps[idx].size) {
        case 8:
          dcArgChar(dcVM,(unsigned char)(ps[idx].v.val & 0xff));
          break;
        case 16:
          dcArgShort(dcVM,(unsigned short)(ps[idx].v.val & 0xffff));
          break;
        default:
          dcArgLong(dcVM,ps[idx].v.val);
        } /* switch */
      } else {
        dcArgPointer(dcVM,ps[idx].v.ptr);
      } /* if */
    } /* for */
    result=(cell)dcCallPointer(dcVM,(void*)LibFunc);
  #else /* HAVE_DYNCALL_H */
    /* push the parameters to the stack (left-to-right in 16-bit; right-to-left
     * in 32-bit)
     */
#if defined __WIN32__ || defined _WIN32 || defined WIN32
    for (idx=paramidx-1; idx>=0; idx--) {
#else
    for (idx=0; idx<paramidx; idx++) {
#endif
      if ((ps[idx].type=='i' || ps[idx].type=='u' || ps[idx].type=='f') && ps[idx].range==1) {
        switch (ps[idx].size) {
        case 8:
          push((unsigned char)(ps[idx].v.val & 0xff));
          break;
        case 16:
          push((unsigned short)(ps[idx].v.val & 0xffff));
          break;
        default:
          push(ps[idx].v.val);
        } /* switch */
      } else {
        push(ps[idx].v.ptr);
      } /* if */
    } /* for */

    /* call the function; all parameters are already pushed to the stack (the
     * function should remove the parameters from the stack)
     */
    result=LibFunc();
  #endif /* HAVE_DYNCALL_H */

  /* store return values and free allocated memory */
  for (idx=0; idx<paramidx; idx++) {
    switch (ps[idx].type) {
    case 'p':
    case 's':
      free(ps[idx].v.ptr);
      break;
    case 'p' | BYREF:
    case 's' | BYREF:
      cptr=amx_Address(amx,params[idx+4]);
      amx_SetString(cptr,(char *)ps[idx].v.ptr,ps[idx].type==('p'|BYREF),sizeof(TCHAR)>1,UNLIMITED);
      free(ps[idx].v.ptr);
      break;
    case 'i':
    case 'u':
    case 'f':
      assert(ps[idx].range==1);
      break;
    case 'i' | BYREF:
    case 'u' | BYREF:
    case 'f' | BYREF:
      cptr=amx_Address(amx,params[idx+4]);
      if (ps[idx].range==1) {
        /* modify directly in the AMX (no memory block was allocated */
        switch (ps[idx].size) {
        case 8:
          *cptr= (ps[idx].type==('i' | BYREF)) ? (long)((signed char)*cptr) : (*cptr & 0xff);
          break;
        case 16:
          *cptr= (ps[idx].type==('i' | BYREF)) ? (long)((short)*cptr) : (*cptr & 0xffff);
          break;
        } /* switch */
      } else {
        int i;
        for (i=0; i<ps[idx].range; i++) {
          switch (ps[idx].size) {
          case 8:
            *cptr= (ps[idx].type==('i' | BYREF)) ? ((signed char*)ps[idx].v.ptr)[i] : ((unsigned char*)ps[idx].v.ptr)[i];
            break;
          case 16:
            *cptr= (ps[idx].type==('i' | BYREF)) ? ((short*)ps[idx].v.ptr)[i] : ((unsigned short*)ps[idx].v.ptr)[i];
            break;
          default:
            *cptr= (ps[idx].type==('i' | BYREF)) ? ((long*)ps[idx].v.ptr)[i] : ((unsigned long*)ps[idx].v.ptr)[i];
          } /* switch */
        } /* for */
        free((char *)ps[idx].v.ptr);
      } /* if */
      break;
    default:
      assert(0);
    } /* switch */
  } /* for */

  return result;
}

/* bool: libfree(const libname[]="")
 * When the name is an empty string, this function frees all libraries (for this
 * abstract machine). The name comparison is case sensitive.
 * Returns true if one or more libraries were freed.
 */
static cell AMX_NATIVE_CALL n_libfree(AMX *amx, const cell *params)
{
  const TCHAR *libname;
  amx_StrParam(amx,params[1],libname);
  return freelib(&ModRoot,amx,libname) > 0;
}

#else /* HAVE_DYNCALL_H || WIN32_FFI */

static cell AMX_NATIVE_CALL n_libcall(AMX *amx, const cell *params)
{
  (void)amx;
  (void)params;
  return 0;
}
예제 #11
0
파일: fixes.cpp 프로젝트: Open-GTO/Fixes2
static cell
	SetTimer_(AMX * amx, cell func, cell delay, cell interval, cell count, cell format, cell * params)
{
	// Advanced version of SetTimer.  Takes four main parameters so that we can
	// have offsets on timers (so they may start after 10ms, then run once every
	// 5ms say), and a COUNT for how many times to run the function!
	// First, find the given function.
	//logprintf("Adding");
	if (delay >= -1 && interval >= 0 && count >= -1)
	{
		char *
			fname;
		STR_PARAM(amx, func, fname);
		int
			idx;
		if (amx_FindPublic(amx, fname, &idx))
		{
			logprintf("fixes.plugin: Could not find function %s.", fname);
		}
		else
		{
			struct timer_s *
				timer;
			try
			{
				timer = new struct timer_s;
			}
			catch (...)
			{
				logprintf("fixes.plugin: Unable to allocate memory.");
				return 0;
			}
			timer->id = ++gCurrentTimer;
			timer->amx = amx;
			timer->func = idx;
			timer->interval = interval * 1000;
			// Need to somehow get the current time.  There is a handy trick here
			// with negative numbers (i.e -1 being "almost straight away").
			timer->trigger = MicrosecondTime() + delay * 1000;
			timer->params = 0;
			timer->repeat = count;
			gTimers.push(timer);
			// Add this timer to the map of timers.
			gHandles[gCurrentTimer] = timer;
			//logprintf("Added %d", timer->trigger);
			if (format)
			{
				char *
					fmat;
				STR_PARAM(amx, format, fmat);
				idx = 0;
				for ( ; ; )
				{
					switch (*fmat++)
					{
						case '\0':
						{
							if (gCurrentTimer == 0xFFFFFFFF)
							{
								logprintf("fixes.plugin: 4294967295 timers created.");
							}
							return (cell)gCurrentTimer;
						}
						case 'i': case 'f': case 'x': case 'h': case 'b': case 'c': case 'l':
						case 'I': case 'F': case 'X': case 'H': case 'B': case 'C': case 'L':
						{
							struct params_s *
								p0 = (struct params_s *)malloc(sizeof (struct params_s));
							if (p0)
							{
								cell *
									cstr;
								amx_GetAddr(amx, params[idx++], &cstr);
								p0->free = 0;
								p0->type = PARAM_TYPE_CELL;
								p0->numData = *cstr; //params[idx++];
								// Construct the list backwards.  Means we don't
								// need to worry about finding the latest one OR
								// the push order, so serves two purposes.
								p0->next = timer->params;
								timer->params = p0;
							}
							else
							{
								DestroyTimer(timer);
								logprintf("fixes.plugin: Unable to allocate memory.");
								return 0;
							}
							break;
						}
						case 's': case 'S':
						{
							cell *
								cstr;
							int
								len;
							amx_GetAddr(amx, params[idx++], &cstr);
							amx_StrLen(cstr, &len);
							struct params_s *
								p0 = (struct params_s *)malloc(sizeof (struct params_s) + len * sizeof (cell) + sizeof (cell));
							if (p0)
							{
								p0->free = 0;
								p0->type = PARAM_TYPE_STRING;
								p0->numData = len + 1;
								memcpy(p0->arrayData, cstr, len * sizeof (cell) + sizeof (cell));
								p0->next = timer->params;
								timer->params = p0;
							}
							else
							{
								DestroyTimer(timer);
								logprintf("fixes.plugin: Unable to allocate memory.");
								return 0;
							}
							break;
						}
						case 'a': case 'A':
						{
							switch (*fmat)
							{
								case 'i': case 'x': case 'h': case 'b':
								case 'I': case 'X': case 'H': case 'B':
								{
									cell *
										cstr;
									amx_GetAddr(amx, params[idx++], &cstr);
									int
										len = params[idx];
									struct params_s *
										p0 = (struct params_s *)malloc(sizeof (struct params_s) + len * sizeof (cell));
									if (p0)
									{
										p0->free = 0;
										p0->type = PARAM_TYPE_ARRAY;
										p0->numData = len;
										memcpy(p0->arrayData, cstr, len * sizeof (cell));
										p0->next = timer->params;
										timer->params = p0;
									}
									else
									{
										DestroyTimer(timer);
										logprintf("fixes.plugin: Unable to allocate memory.");
										return 0;
									}
									break;
								}
								default:
								{
									logprintf("fixes.plugin: Array with no length.");
								}
							}
							break;
						}
					}
				}
			}
			else
			{
				if (gCurrentTimer == 0xFFFFFFFF)
				{
					logprintf("fixes.plugin: 4294967295 timers created.");
				}
				return (cell)gCurrentTimer;
			}
		}
	}
	else
	{
		logprintf("fixes.plugin: Invalid timer parameter.");
	}
	return 0;
}
예제 #12
0
cell AMX_NATIVE_CALL amx_DC_CMD(AMX* amx, cell* params)
{
	cell *addr;
	int len;
	amx_GetAddr(amx, params[2], &addr);
	amx_StrLen(addr, &len);
	if(len>127) len=127;
	++len;
	char cmdtext[128];
	amx_GetString(cmdtext, addr, 0, len);
	cmdtext[0] = '_';
	// converting string to lower case
	int pos=0, cmd_end;
	do{
		++pos;
		if(('A' <= cmdtext[pos]) && (cmdtext[pos] <= 'Z'))
			cmdtext[pos] += ('a'-'A');
		else if(cmdtext[pos] == '\0')
			break;
		else if(cmdtext[pos] == ' ')
		{
			cmd_end = pos;
			cmdtext[pos++] = '\0';
			goto loop1_exit;
		}
	}while(1);
	cmd_end = 0;
loop1_exit:
	// search for command index in all AMX instances
	int pubidx;
	cell retval, params_addr;
	int i;
	for(i=0; i<=lastAMX; ++i)
	{
		if((amx_List[i].amx != NULL) && (amx_FindPublic(amx_List[i].amx, cmdtext, &pubidx) == AMX_ERR_NONE))
		{
			// if current AMX instance has OnPlayerCommandReceived callback - invoke it
			if(amx_List[i].OPCR != 0x7FFFFFFF)
			{
				// restore some symbols in cmdtext
				cmdtext[0] = '/';
				if(cmd_end>0)
					cmdtext[cmd_end] = ' ';
				amx_PushString(amx_List[i].amx, &params_addr, 0, cmdtext, 0, 0);
				amx_Push(amx_List[i].amx, params[1]);
				amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR);
				amx_Release(amx_List[i].amx, params_addr);
				// if OPCR returned 0 - command execution rejected
				if(retval == 0)
					return 1;
				cmdtext[0] = '_';	// restore AMX-styled command name
				if(cmd_end>0)		// and separate it from parameters (again =/)
					cmdtext[cmd_end] = ' ';
			}
			// remove extra space characters between command name and parameters
			while(cmdtext[pos] == ' ') pos++;
			amx_PushString(amx_List[i].amx, &params_addr, 0, cmdtext+pos, 0, 0);
			amx_Push(amx_List[i].amx, params[1]);
			amx_Exec(amx_List[i].amx, &retval, pubidx);
			amx_Release(amx_List[i].amx, params_addr);
			// if current AMX instance has OnPlayerCommandPerformed callback - invoke it
			if(amx_List[i].OPCP != 0x7FFFFFFF)
			{
				cmdtext[0] = '/';
				if(cmd_end>0)
					cmdtext[cmd_end] = ' ';
				amx_Push(amx_List[i].amx, retval);
				amx_PushString(amx_List[i].amx, &params_addr, 0, cmdtext, 0, 0);
				amx_Push(amx_List[i].amx, params[1]);
				amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP);
				amx_Release(amx_List[i].amx, params_addr);
			}
			return 1;
		}
	}
	// if command wasn't found - perhaps this is an alternative command
	if(Alts_n != 0)
	{
		int hash;
		// remove extra space characters between command name and parameters
		//logprintf("attempting to find alt %s, len = %d", cmdtext, (cmdtext[pos])?(pos-1):(pos));
		Murmur3(cmdtext, (cmdtext[pos])?(pos-1):(pos), &hash);
		if(cmdtext[pos])
		{
			pos--;
			while(cmdtext[++pos] == ' '){}
		}
		//logprintf((char*)"Murmur3(%s) = 0x%X", cmdtext, hash);
		boost::unordered_map<int,int>::const_iterator alt;
		for(i=0; i<=lastAMX; ++i)
		{
			if((amx_List[i].amx != NULL) && ((alt = Alts[i].find(hash)) != Alts[i].end()))
			{
				pubidx = alt->second;
				//logprintf("found alt: %s, amx = %d, idx = %d", cmdtext, (int)amx, pubidx);
				if(amx_List[i].OPCR != 0x7FFFFFFF)
				{
					// restore some symbols in cmdtext
					cmdtext[0] = '/';
					if(cmd_end>0)
						cmdtext[cmd_end] = ' ';
					amx_PushString(amx_List[i].amx, &params_addr, 0, cmdtext, 0, 0);
					amx_Push(amx_List[i].amx, params[1]);
					amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR);
					amx_Release(amx_List[i].amx, params_addr);
					// if OPCR returned 0 - command execution rejected
					if(retval == 0)
						return 1;
					cmdtext[0] = '_';	// restore AMX-styled command name
					if(cmd_end>0)		// and separate it from parameters (again =/)
						cmdtext[cmd_end] = ' ';
				}
				// remove extra space characters between command name and parameters
				while(cmdtext[pos] == ' ') pos++;
				amx_PushString(amx_List[i].amx, &params_addr, 0, cmdtext+pos, 0, 0);
				amx_Push(amx_List[i].amx, params[1]);
				amx_Exec(amx_List[i].amx, &retval, pubidx);
				amx_Release(amx_List[i].amx, params_addr);
				// if current AMX instance has OnPlayerCommandPerformed callback - invoke it
				if(amx_List[i].OPCP != 0x7FFFFFFF)
				{
					cmdtext[0] = '/';
					if(cmd_end>0)
						cmdtext[cmd_end] = ' ';
					amx_Push(amx_List[i].amx, retval);
					amx_PushString(amx_List[i].amx, &params_addr, 0, cmdtext, 0, 0);
					amx_Push(amx_List[i].amx, params[1]);
					amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP);
					amx_Release(amx_List[i].amx, params_addr);
				}
				return 1;
			}
		}
	}
	// if command not found - call OnPlayerCommandPerformed callback in gamemode AMX (success = -1)
	if(amx_List[0].OPCP != 0x7FFFFFFF)
	{
		cmdtext[0] = '/';
		if(cmd_end>0)
			cmdtext[cmd_end] = ' ';
		amx_Push(amx_List[0].amx, -1);
		amx_PushString(amx_List[0].amx, &params_addr, 0, cmdtext, 0, 0);
		amx_Push(amx_List[0].amx, params[1]);
		amx_Exec(amx_List[0].amx, &retval, amx_List[0].OPCP);
		amx_Release(amx_List[0].amx, params_addr);
	}
	return 1;
}
예제 #13
0
cell AMX_NATIVE_CALL amx_RegisterAlt(AMX* amx, cell* params)
{
	int amx_n;
	for(amx_n=0; amx_n<=lastAMX; ++amx_n)
		if(amx == amx_List[amx_n].amx)
			break;
	if(amx_n>lastAMX) // if amx wasn't found in list
		return 0;
	cell *addr;
	int len;
	amx_GetAddr(amx, params[1], &addr);
	amx_StrLen(addr, &len);
	if(len>31) len=31;
	++len;
	char cmd[32];
	amx_GetString(cmd, addr, 0, len);
	cmd[0] = '_';
	// converting string to lower case
	int pos=0;
	do{
		++pos;
		if(('A' <= cmd[pos]) && (cmd[pos] <= 'Z'))
			cmd[pos] += ('a'-'A');
		else if(cmd[pos] == '\0')
			break;
		else if((cmd[pos] == ' ') || (cmd[pos] == '\t'))
		{
			cmd[pos] = '\0';
			break;
		}
	}while(1);
	int pubidx;
	if(amx_FindPublic(amx, cmd, &pubidx) != AMX_ERR_NONE)
	{
		//logprintf((char*)"RegisterAlt: Couldn't find function %s", cmd);
		return 1;
	}
	int alt_n = (params[0]/4), hash;
	//logprintf("RegisterAlt: alts = %d", alt_n-1);
	do{
		if(amx_GetAddr(amx, params[alt_n], &addr) != AMX_ERR_NONE)
			continue;
		amx_StrLen(addr, &len);
		if(len>31) len=31; // command length must be up to 31 chars
		++len;
		amx_GetString(cmd, addr, 0, len);
		cmd[0] = '_';
		pos = 0;
		do{
			++pos;
			if(('A' <= cmd[pos]) && (cmd[pos] <= 'Z'))
				cmd[pos] += ('a'-'A');
			else if(cmd[pos] == '\0')
				break;
			else if((cmd[pos] == ' ') || (cmd[pos] == '\t'))
			{
				cmd[pos] = '\0';
				break;
			}
		}while(1);
		//logprintf((char*)"%s, len = %d", cmd, pos);
		Murmur3(cmd, pos, &hash);
		//logprintf("RegisterAlt: Murmur3(%s) = 0x%X", cmd, hash);
		Alts[amx_n].insert(std::make_pair(hash, pubidx));
		Alts_n++;
		//logprintf((char*)"RegisterAlt: new alt - %s, amx = %d, pubidx = %d", cmd, amx, pubidx);
	}while(--alt_n > 1);
	return 1;
}
예제 #14
0
// native mysql_statement_execute(connectionHandle, statementId, callback[], dataId, {Float,_}:...);
static cell AMX_NATIVE_CALL n_mysql_statement_execute(AMX* amx, cell* params) {
  if (params[0] < 4 * sizeof(cell)) {
    logprintf("SCRIPT: Bad parameter count (%d < 4): ", params[0]);
    return 0;
  }

  ConnectionHost* connection = connectionController->connection(params[1]);
  const Statement* statement = statementRegistry->At(params[2]);
  if (connection == nullptr || statement == nullptr)
    return 0;

  char* callback;
  amx_StrParam(amx, params[3], callback);

  unsigned int dataId = params[4];
  const int parameterOffset = 4;

  if ((statement->Parameters().length() + parameterOffset) * sizeof(cell) != params[0]) {
    logprintf("[lvp_MySQL] The statement call expected %d parameters, received %d.", statement->Parameters().length() + parameterOffset, params[0] / sizeof(cell));
    logprintf("[lvp_MySQL] Statement: [%s].", statement->Query().c_str());
    return 0;
  }

  std::vector<std::string> parameters;
  const std::string& parameterTypes = statement->Parameters();
  
  char buffer[256];
  cell* address;
  int length = 0;

  for (unsigned int index = 0; index < parameterTypes.length(); ++index) {
    if (amx_GetAddr(amx, params[parameterOffset + 1 + index], &address) != AMX_ERR_NONE)
      return 0; // this case shouldn't happen.

    switch (parameterTypes[index]) {
      case 'i': // integers.
        snprintf(buffer, sizeof(buffer), "%d", *address);
        parameters.push_back(buffer);
        break;

      case 'f': // floats.
        snprintf(buffer, sizeof(buffer), "%.4f", amx_ctof(*address));
        parameters.push_back(buffer);
        break;

      case 's': // strings.
        amx_StrLen(address, &length);
        amx_GetString(buffer, address, 0, std::min(static_cast<unsigned int>(length + 1), sizeof(buffer)));
        buffer[sizeof(buffer)-1] = 0;

        parameters.push_back(escape_string_parameter(buffer));
        break;

      default: // other (unhandled) types.
        logprintf("[lvp_MySQL] Unknown parameter type in statement: '%c'. Cannot execute.", parameterTypes[index]);
        logprintf("[lvp_MySQL] Statement: [%s].", statement->Query().c_str());
        return 0;
    }
  }
  
  std::string query;
  if (QueryBuilder::Build(statement, parameters, query) == false) {
    logprintf("[lvp_MySQL] Unable to build the query, cannot execute this statement.");
    logprintf("[lvp_MySQL] Statement: [%s].", statement->Query().c_str());
    return 0;
  }

  connection->query(query.c_str(), callback, dataId);
  return 1;
}