⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbfunct.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 */
BOOL getNextExpired(UINT8* channelId)
{
   if (nextExpChNbrListInd >= expChNbrListSize)
      return FALSE;

   *channelId = expChNbrList[nextExpChNbrListInd];
   nextExpChNbrListInd++;
   return TRUE;
}


/*
 * Add a host to the specified channel. The string pointed out
 * by 'host' is copied and not taken over by the database.
 *
 * The string pointed out by 'host' must include a host name which
 * may be followed by a path name. The first '/' delimits the host from
 * the path. The host name may be the empty string.
 *
 * An object or a data channel is created if either is missing.
 *
 * 'length' is the length of host including any path but excluding an  
 * optional terminating EOL.
 */
void addHost(UINT8 object, UINT8 channel, const BYTE* host, UINT16 length)
{
   ChannelListPtr channelStruct;
   DataUnion      newHost;
   UINT8          error;

   if (host == NULL)
      return;
   if (length && (host[length-1] == '\0'))    /* Null terminated, even  */
      if (--length == 0)                      /* though it shouldn't be */ 
         return;

   channelStruct = getObjectOrChannel_add(object, channel, TRUE).channelStruct;
   if (channelStruct == NULL)
      return;

   newHost.s = dupSubStr(host, host + length);
   #ifndef HAS_SETJMP
   if (newHost.s == NULL)
      return;
   #endif

   /* Create new element */
   db_createNewElement(channelStruct->hostPtr, NULL, DB_flag_str | DB_flag_dataExternal,
                       newHost, NULL, NULL, &error);
   /* Insert new flags, when introduced in wipdb.c */
	 /* BOOKMARK:FLAGS */
}



/*
 * Remove a host, if found, from the named channel.
 * 
 * The string pointed out by 'host' must include a host name which
 * may be followed by a path name. The first '/' delimits the host from
 * the path. The host name may be the empty string.
 *
 * 'length' is the length of host including any path but excluding an  
 * optional terminating EOL.
 *
 * Calling deleteHost, the 'host'
 * string must match the host and any path to be deleted.
 * When matching, the host part is compared case insensitively while any path
 * part is compared case sensitively.
 */
void deleteHost(UINT8 object, UINT8 channel, const BYTE* host, UINT16 length)
{
   ChannelListPtr channelStruct;
   ElementPtr     element;
   ElementPtr     prev;
   ElementPtr     hostPtr;
   BYTE*          s;
   const BYTE*    t;
   UINT16         i;
   BOOL           caseSens;

   if (host == NULL || length == 0)
      return;
   if (host[length-1] == '\0')
      if (--length == 0)
         return;

   channelStruct = getChannel(object, channel);
   if (channelStruct == NULL)
      return;
   hostPtr = (ElementPtr) channelStruct->hostPtr;

   /* Search through all channels, until a match is found */
   for (element = hostPtr->data.e, prev = NULL;
        element != (ElementPtr) hostPtr;
        prev = element, element = element->next) {
      caseSens = FALSE;
      s = element->data.s;
      for (t=host, i=length; ; s++, t++) {
         if (!caseSens && (*s == '/'))
            caseSens = TRUE;
         if (caseSens && (*s != *t))
            goto Next_loop;
         if (!caseSens && (latin1_lc[*s] != latin1_lc[*t]))
            goto Next_loop;
         if (--i == 0)
            if (!*(s+1))
               break;
            else
               goto Next_loop;
      }

      /* Delete element */
      if (prev == NULL)
         hostPtr->data.p = element->next;
      else {
         prev->next = element->next;
         if (prev->next == hostPtr)
            prev->flags |= DB_flag_lastElement;
      }
      OSConnectorFree(element->data.s); 
      OSConnectorFree(element);
      return;
Next_loop:;
   }
}



/* ======== admin ======== */

/*
 * Initiate structures connected to data channel handling.
 */
void dataChannelInit(void)
{
   ChannelListPtr channelList;
   ObjectListPtr  objectRecord;
   BYTE*          temp;
   UINT8          error;

   objectList = (ObjectListPtr) OSConnectorAlloc(sizeof(ObjectList));
   #ifndef HAS_SETJMP
   if (objectList == NULL)
      return;
   #endif
   objectListSize = 1;

   globalRef = db_createRecord(DB_root, (BYTE*) "globl", DB_rec, &error);
   obj00Ref  = db_createRecord(globalRef, (BYTE*) "obj00", DB_rec, &error);

   channelList = (ChannelListPtr) OSConnectorAlloc(sizeof(ChannelList));

   objectRecord = &objectList[0];
   objectRecord->objectRef       = obj00Ref;
   objectRecord->channelListSize = 0;
   objectRecord->objectNbr       = 0;
   objectRecord->defaultChannel  = -1;
   objectRecord->channelList     = channelList;

   /* Fields added to the global object */

   db_setInt(globalRef, (BYTE*) CACHE_AGE, 86400);  /* Cache age      */
   db_setInt(globalRef, (BYTE*) CACHE_MODE, 1);     /* Cache mode     */
   db_setInt(globalRef, (BYTE*) COOKIES_ENABLED, 1);/* Using cookies  */
   if (db_setStr(globalRef, (BYTE*) USER_AGENT, temp = B_STRDUP((BYTE*) "WAPPER")))
      OSConnectorFree(temp);                        /* User agent     */

   /* Fields added to the object template */

   db_setInt(obj00Ref, (BYTE*) HISTORY_SIZE, 10);   /* History size   */
   db_setInt(obj00Ref, (BYTE*) DISPLAY_IMAGES, 1);  /* Display images */
   db_setInt(obj00Ref, (BYTE*) UPDATE_IMAGES, 0);   /* Update images  */
}



/* 
 * Remove all structures associated with objects and data
 * channels. To be called when closing down the database.
 */
void dataChannelTerminate(void) {
   int i;

   for (i=0; i < objectListSize; i++) 
      OSConnectorFree(objectList[i].channelList);
   OSConnectorFree(objectList);
}







/*************************************************************/
/**********************  authenticate  ***********************/
/*************************************************************/

/*

STRUCTURE

The database structure used to save authentication information
is arranged like this:

root
  |
  authP ---- authH
    |          |
    proxy      host
      |         |
      |         <> ------------------------------ <> ---------------------------- <> ---
      |          |                                 |
      |          host --- realm --- cred           host --- realm --- cred
      |            |        |         |             |        |         |
      |            string   string    mem           string   string    mem
      |
      |
      <> ---------------------------- <> --------------------------- <> ---
       |                               |
       addr --- port --- cred          addr --- port --- cred
        |                 |             |                 |
        string            mem           string            mem


Name    type  comment
---------------------
authP - rec   write-through
authH - rec   write-through
proxy - set   proxy authentication list
host  - set   host authentication list
<>    - rec   nameless record
host  - str   host taken from URL
realm - str   realm
cred  - mem   credentials
addr  - str   address of proxy
port  - int   port number

The order of elements within a list is significant for the
addr-port-cred and host-realm-cred lists.

The 'authH' record is write through and thus the entire structure.
The 'authP' record is not saved persistently.

Two counters (hostAuthSize and proxyAuthSize) are used for saving
the list lengths. They can be at most maxHostListSize resp.
maxProxyAuthSize elements long. 


SEARCHING

Searching for a matching host is not done in the same way as is
done for proxies. The host find function (checkHostAuth) is 
called in two cases: before a http request and when a request
results in a challange for authenification. In the first case,
checkHostAuth is called with no realm and the matching is done
based on only the host. Even if the item exists in the database,
a mismatch may occur. This can happen if several items with
identical host are in the database. A mismatch will result in a
challenge for the server, containing the correct realm and the
correct credentials can be found.

When found an match, this item is moved first in list for three
reasons. 
1. When the list is full the least reasently used item
   (i.e. last element in the list) is deleted.
2. When searching, it is likely that the item searched for is
   the same as last time, especially for proxies.
3. If searching for a host without a realm, the first matching
   item is used. If this is not the correct on, a realm is
   returned and the correct one is placed ahead of the wrong one.
   The next lookup for the same host will probably be for the
   same realm.

The third case can be solved a little more elegant by saving the
path along with the host. Out of the paths, a more inteligen
guess can be made. Still, it is not foolproof and demands 
more code, a larger amount of RAM and more persistent memory
will be locked up. Add to this, it will be slower. If sending
alternating requests to the same host, but using different
realms is a frequent operation, then it will probably worthwhile
to implement such a solution.

The host and realm are both text strings and are matched agaist
the database case insensitivily.

The address can contain any data not only character data and is
only an exact match counts when comparing addresses.

*/



/*************
 * Constants *
 *************/

enum {
   /* Must be at least 2 */
   maxHostListSize  = cfg_wae_wspif_AuthenticationItems,                  
   maxProxyListSize = cfg_wae_wspif_AuthenticationItems
};


/*********
 * Types *
 *********/


/*************
 * Variables *
 *************/

static RecordPtr hostListRec;             /* Pointer to host list record */ 
static RecordPtr proxyListRec;            /* Pointer to proxy list record */ 

static UINT8 hostAuthSize;                /* Number of site authentification records in database. */
static UINT8 proxyAuthSize;               /* Number of proxy authentification records in database. */


/*************
 * Functions *
 *************/


/* ======== host ======== */

/*
 * Find host in database. Functionality common to storeHostAuth
 * and checkHostAuth is located in this function.
 *
 * Matches the host of 'url' and 'realm', if not NULL.
 *
 * Return TRUE if match found.
 */
BOOL findHost(BYTE* *url, BYTE* realm, BYTE* *endPointer, RecordPtr *currentRec)
{
   RecordPtr rec;
   RecordPtr tempRec;
   BYTE*     endPtr;
   BYTE*     s;
   BYTE*     t;

   /* The url is known to be a well formatted http/https URL */
   
   s = *url;
   while (*s++ != ':')
      ;
   *url = s + 2;
   for (endPtr=*url; *endPtr!='\0' && *endPtr!='/' && *endPtr!=':' &&
                    *endPtr!='?'  && *endPtr!='#'; endPtr++)
      ;

   /* Search for matching host and realm */
   rec = NULL;
   for (tempRec = hostListRec->data.r; tempRec != hostListRec;
        tempRec = (RecordPtr) rec->next) {
      rec = tempRec;
      for (s = rec->data.f->data.s, t = *url; ; s++, t++) {
         if (latin1_lc[*s] != latin1_lc[*t])
            if (!*s && t == endPtr)
               break;
            else
               goto Next_loop;
         if (!*s)
            break;
      }
      /* Host found, check realm */
      if (realm != NULL) {
         for (s=rec->data.f->next->data.s, t=realm; ;s++, t++)
            if (latin1_lc[*s] == latin1_lc[*t] && !*s)
               goto Match_found;
      } else
         goto Match_found;
Next_loop:;
   }

   /* --- No match found ---*/
   *endPointer  = endPtr;
   *currentRec  = rec;
   return FALSE;
   

   /* --- Matching host and realm (if present) found --- */
Match_found:

   /* Move current record first in queue. Nessesary if several
    * realms are connected to a single host.*/
   if (hostListRec->data.r != rec) 
      db_moveToFront(hostListRec, (ElementPtr) rec);

   *currentRec = rec;
   return TRUE;
}



/*
 * Store the host of 'url' together with 'realm' and 'credientials'.
 * If already cfg_wae_wspif_AuthenticationItems are present, the
 * least reasently used element is replaced by the new one.
 *
 * If host and 'realm' matches an item, then the credentials are
 * uppdated to 'credentials'. The host and 'realm' are text
 * strings and are matched agaist the database case insensitivily.
 *
 * Return TRUE if successfull.
 */
BOOL storeHostAuth(BYTE* url, BYTE* realm, BYTE* credentials, UINT8 credLength)
{
   DB_ref    ref;
   RecordPtr rec;
   BYTE*     endPtr;
   BYTE*     host;
   BYTE*     cred;
   BYTE*     s;
   BYTE*     t;
   UINT8     error;

   if (!url || !realm || !credentials)
      return FALSE;

   cred = (BYTE*) OSConnectorAlloc(credLength+2);
   #ifndef HAS_SETJMP
   if (cred == NULL)
      return FALSE;
   #endif
   *(UINT16*) cred = credLength + 2;
   memcpy(cred+2, credentials, credLength);

   /* Update or create host information */
   if (findHost(&url, realm, &endPtr, &rec))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -