internal AEgypten bugfix #1131: get full list of emails stored in certificated used...
authorKarl-Heinz Zimmer <khz@kde.org>
Fri, 28 Jun 2002 14:12:18 +0000 (14:12 +0000)
committerKarl-Heinz Zimmer <khz@kde.org>
Fri, 28 Jun 2002 14:12:18 +0000 (14:12 +0000)
gpgmeplug/cryptplug.h
gpgmeplug/gpgmeplug.c

index 6d901d9..26a7e90 100644 (file)
@@ -1518,8 +1518,9 @@ struct SignatureMetaDataExtendedInfo
     char* algo;
     char* userid;
     char* name;
-    char* email;
     char* comment;
+    char** emailList;
+    int    emailCount;
     unsigned long algo_num;
     unsigned long validity;
     unsigned long userid_num;
index 3774b51..c30f451 100644 (file)
@@ -1239,254 +1239,6 @@ err = 0;
 }
 
 
-static const char*
-sig_status_to_string( GpgmeSigStat status )
-{
-  const char *result;
-
-  switch (status) {
-    case GPGME_SIG_STAT_NONE:
-      result = "Oops: Signature not verified";
-      break;
-    case GPGME_SIG_STAT_NOSIG:
-      result = "No signature found";
-      break;
-    case GPGME_SIG_STAT_GOOD:
-      result = "Good signature";
-      break;
-    case GPGME_SIG_STAT_BAD:
-      result = "BAD signature";
-      break;
-    case GPGME_SIG_STAT_NOKEY:
-      result = "No public key to verify the signature";
-      break;
-    case GPGME_SIG_STAT_ERROR:
-      result = "Error verifying the signature";
-      break;
-    case GPGME_SIG_STAT_DIFF:
-      result = "Different results for signatures";
-      break;
-    default:
-      result = "Error: Unknown status";
-      break;
-  }
-
-  return result;
-}
-
-
-bool checkMessageSignature( char** cleartext,
-                            const char* signaturetext,
-                            bool signatureIsBinary,
-                            int signatureLen,
-                            struct SignatureMetaData* sigmeta )
-{
-  GpgmeCtx ctx;
-  GpgmeSigStat status;
-  unsigned long sumGPGME;
-  SigStatusFlags sumPlug;
-  GpgmeData datapart, sigpart;
-  char* rClear = 0;
-  size_t clearLen;
-  GpgmeError err;
-  GpgmeKey key;
-  time_t created;
-  int sig_idx = 0;
-  const char* statusStr;
-  const char* fpr;
-  bool isOpaqueSigned;
-
-  if( !cleartext ) {
-    if( sigmeta )
-      storeNewCharPtr( &sigmeta->status,
-                        __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
-
-    return false;
-  }
-
-  isOpaqueSigned = !*cleartext;
-
-  gpgme_new( &ctx );
-  gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
-  gpgme_set_armor (ctx,    signatureIsBinary ? 0 : 1);
-  /*  gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1); */
-
-  if( isOpaqueSigned )
-    gpgme_data_new( &datapart );
-  else
-    gpgme_data_new_from_mem( &datapart, *cleartext,
-                             strlen( *cleartext ), 1 );
-
-  gpgme_data_new_from_mem( &sigpart,
-                           signaturetext,
-                           signatureIsBinary
-                           ? signatureLen
-                           : strlen( signaturetext ),
-                           1 );
-
-  gpgme_op_verify( ctx, sigpart, datapart, &status );
-
-  if( isOpaqueSigned ) {
-    rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
-    *cleartext = malloc( clearLen + 1 );
-    if( *cleartext ) {
-      if( clearLen )
-        strncpy(*cleartext, rClear, clearLen );
-      (*cleartext)[clearLen] = '\0';
-    }
-    free( rClear );
-  }
-  else
-    gpgme_data_release( datapart );
-
-  gpgme_data_release( sigpart );
-
-  /* Provide information in the sigmeta struct */
-  /* the status string */
-  statusStr = sig_status_to_string( status );
-  sigmeta->status = malloc( strlen( statusStr ) + 1 );
-  if( sigmeta->status ) {
-    strcpy( sigmeta->status, statusStr );
-    sigmeta->status[strlen( statusStr )] = '\0';
-  } else
-    ; /* nothing to do, is already 0 */
-
-  /* Extended information for any number of signatures. */
-  fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
-  sigmeta->extended_info = 0;
-  while( fpr != NULL ) {
-    struct tm* ctime_val;
-    const char* sig_status;
-
-    void* realloc_return = realloc( sigmeta->extended_info,
-                                    sizeof( struct SignatureMetaDataExtendedInfo ) * ( sig_idx + 1 ) );
-    if( realloc_return ) {
-      sigmeta->extended_info = realloc_return;
-
-      /* clear the data area */
-      memset( &sigmeta->extended_info[sig_idx], 0, sizeof (struct SignatureMetaDataExtendedInfo) );
-
-      /* the creation time */
-      sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
-      if( sigmeta->extended_info[sig_idx].creation_time ) {
-        ctime_val = localtime( &created );
-        memcpy( sigmeta->extended_info[sig_idx].creation_time,
-                ctime_val, sizeof( struct tm ) );
-      }
-
-      /* the extended signature verification status */
-      sumGPGME = gpgme_get_sig_ulong_attr( ctx,
-                                           sig_idx,
-                                           GPGME_ATTR_SIG_SUMMARY,
-                                           0 );
-      // translate GPGME status flags to common CryptPlug status flags
-      sumPlug = 0;
-      if( sumGPGME & GPGME_SIGSUM_VALID       ) sumPlug |= SigStat_VALID      ;
-      if( sumGPGME & GPGME_SIGSUM_GREEN       ) sumPlug |= SigStat_GREEN      ;
-      if( sumGPGME & GPGME_SIGSUM_RED         ) sumPlug |= SigStat_RED        ;
-      if( sumGPGME & GPGME_SIGSUM_KEY_REVOKED ) sumPlug |= SigStat_KEY_REVOKED;
-      if( sumGPGME & GPGME_SIGSUM_KEY_EXPIRED ) sumPlug |= SigStat_KEY_EXPIRED;
-      if( sumGPGME & GPGME_SIGSUM_SIG_EXPIRED ) sumPlug |= SigStat_SIG_EXPIRED;
-      if( sumGPGME & GPGME_SIGSUM_KEY_MISSING ) sumPlug |= SigStat_KEY_MISSING;
-      if( sumGPGME & GPGME_SIGSUM_CRL_MISSING ) sumPlug |= SigStat_CRL_MISSING;
-      if( sumGPGME & GPGME_SIGSUM_CRL_TOO_OLD ) sumPlug |= SigStat_CRL_TOO_OLD;
-      if( sumGPGME & GPGME_SIGSUM_BAD_POLICY  ) sumPlug |= SigStat_BAD_POLICY ;
-      if( sumGPGME & GPGME_SIGSUM_SYS_ERROR   ) sumPlug |= SigStat_SYS_ERROR  ;
-      if( !sumPlug )
-        sumPlug = SigStat_NUMERICAL_CODE | sumGPGME;
-      sigmeta->extended_info[sig_idx].sigStatusFlags = sumPlug;
-
-      sigmeta->extended_info[sig_idx].validity = GPGME_VALIDITY_UNKNOWN;
-
-      err = gpgme_get_sig_key (ctx, sig_idx, &key);
-
-      if ( err == GPGME_No_Error) {
-        const char* attr_string;
-        unsigned long attr_ulong;
-
-        /* extract key identidy */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_KEYID, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].keyid, attr_string );
-
-        /* extract finger print */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_FPR, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint,
-                            attr_string );
-
-        /* algorithms useable with this key */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_ALGO, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].algo,
-                            attr_string );
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_ALGO, 0, 0);
-        sigmeta->extended_info[sig_idx].algo_num = attr_ulong;
-
-        /* extract key validity */
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_VALIDITY, 0, 0);
-        sigmeta->extended_info[sig_idx].validity = attr_ulong;
-
-        /* extract user id, according to the documentation it's representable
-        * as a number, but it seems that it also has a string representation
-        */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].userid,
-                            attr_string );
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_USERID, 0, 0);
-        sigmeta->extended_info[sig_idx].userid_num = attr_ulong;
-
-        /* extract the length */
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_LEN, 0, 0);
-        sigmeta->extended_info[sig_idx].keylen = attr_ulong;
-
-        /* extract the creation time of the key */
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_CREATED, 0, 0);
-        sigmeta->extended_info[sig_idx].key_created = attr_ulong;
-
-        /* extract the expiration time of the key */
-        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_EXPIRE, 0, 0);
-        sigmeta->extended_info[sig_idx].key_expires = attr_ulong;
-
-        /* extract user name */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_NAME, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].name,
-                            attr_string );
-
-        /* extract email */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_EMAIL, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].email,
-                            attr_string );
-
-        /* extract the comment */
-        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_COMMENT, 0, 0);
-        if (attr_string != 0)
-            storeNewCharPtr( &sigmeta->extended_info[sig_idx].comment,
-                            attr_string );
-      }
-      else
-        storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint, fpr );
-
-      sig_status = sig_status_to_string( status );
-      storeNewCharPtr( &sigmeta->extended_info[sig_idx].status_text,
-                       sig_status );
-
-    } else
-      break; /* if allocation fails once, it isn't likely to
-                succeed the next time either */
-
-    fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
-  }
-  sigmeta->extended_info_count = sig_idx;
-  sigmeta->nota_xml = gpgme_get_notation( ctx );
-  sigmeta->status_code = status;
-
-  gpgme_release( ctx );
-  return ( status == GPGME_SIG_STAT_GOOD );
-}
 
 bool storeCertificatesFromMessage(
         const char* ciphertext ){ return true; }
@@ -2584,7 +2336,7 @@ bool findCertificates( const char* addressee,
           siz += strlen( openBracket );
           siz += strlen( s2 );
           siz += strlen( closeBracket );
-          DNs[ nFound ] = xstrdup( dn );
+          DNs[ nFound ] = dn;
           FPRs[nFound ] = xstrdup( s2 );
           ++nFound;
           if( nFound >= maxCerts ) {
@@ -2628,3 +2380,292 @@ bool findCertificates( const char* addressee,
     
   return ( 0 < nFound );
 }
+
+
+static const char*
+sig_status_to_string( GpgmeSigStat status )
+{
+  const char *result;
+
+  switch (status) {
+    case GPGME_SIG_STAT_NONE:
+      result = "Oops: Signature not verified";
+      break;
+    case GPGME_SIG_STAT_NOSIG:
+      result = "No signature found";
+      break;
+    case GPGME_SIG_STAT_GOOD:
+      result = "Good signature";
+      break;
+    case GPGME_SIG_STAT_BAD:
+      result = "BAD signature";
+      break;
+    case GPGME_SIG_STAT_NOKEY:
+      result = "No public key to verify the signature";
+      break;
+    case GPGME_SIG_STAT_ERROR:
+      result = "Error verifying the signature";
+      break;
+    case GPGME_SIG_STAT_DIFF:
+      result = "Different results for signatures";
+      break;
+    default:
+      result = "Error: Unknown status";
+      break;
+  }
+
+  return result;
+}
+
+
+bool checkMessageSignature( char** cleartext,
+                            const char* signaturetext,
+                            bool signatureIsBinary,
+                            int signatureLen,
+                            struct SignatureMetaData* sigmeta )
+{
+  GpgmeCtx ctx;
+  GpgmeSigStat status;
+  unsigned long sumGPGME;
+  SigStatusFlags sumPlug;
+  GpgmeData datapart, sigpart;
+  char* rClear = 0;
+  size_t clearLen;
+  GpgmeError err;
+  GpgmeKey key;
+  time_t created;
+  struct DnPair* a;
+  char* dn;
+  int sig_idx=0;
+  int UID_idx=0;
+  const char* statusStr;
+  const char* fpr;
+  bool isOpaqueSigned;
+  
+  if( !cleartext ) {
+    if( sigmeta )
+      storeNewCharPtr( &sigmeta->status,
+                        __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
+
+    return false;
+  }
+
+  isOpaqueSigned = !*cleartext;
+
+  gpgme_new( &ctx );
+  gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+  gpgme_set_armor (ctx,    signatureIsBinary ? 0 : 1);
+  /*  gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1); */
+
+  if( isOpaqueSigned )
+    gpgme_data_new( &datapart );
+  else
+    gpgme_data_new_from_mem( &datapart, *cleartext,
+                             strlen( *cleartext ), 1 );
+
+  gpgme_data_new_from_mem( &sigpart,
+                           signaturetext,
+                           signatureIsBinary
+                           ? signatureLen
+                           : strlen( signaturetext ),
+                           1 );
+
+  gpgme_op_verify( ctx, sigpart, datapart, &status );
+
+  if( isOpaqueSigned ) {
+    rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
+    *cleartext = malloc( clearLen + 1 );
+    if( *cleartext ) {
+      if( clearLen )
+        strncpy(*cleartext, rClear, clearLen );
+      (*cleartext)[clearLen] = '\0';
+    }
+    free( rClear );
+  }
+  else
+    gpgme_data_release( datapart );
+
+  gpgme_data_release( sigpart );
+
+  /* Provide information in the sigmeta struct */
+  /* the status string */
+  statusStr = sig_status_to_string( status );
+  sigmeta->status = malloc( strlen( statusStr ) + 1 );
+  if( sigmeta->status ) {
+    strcpy( sigmeta->status, statusStr );
+    sigmeta->status[strlen( statusStr )] = '\0';
+  } else
+    ; /* nothing to do, is already 0 */
+
+  /* Extended information for any number of signatures. */
+  fpr = gpgme_get_sig_status( ctx, sig_idx, &status, &created );
+  sigmeta->extended_info = 0;
+  while( fpr != NULL ) {
+    struct tm* ctime_val;
+    const char* sig_status;
+
+    void* alloc_return = realloc( sigmeta->extended_info,
+                                  sizeof( struct SignatureMetaDataExtendedInfo )
+                                  * ( sig_idx + 1 ) );
+    if( alloc_return ) {
+      sigmeta->extended_info = alloc_return;
+
+      /* clear the data area */
+      memset( &sigmeta->extended_info[sig_idx], 
+              0,
+              sizeof (struct SignatureMetaDataExtendedInfo) );
+
+      /* the creation time */
+      sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
+      if( sigmeta->extended_info[sig_idx].creation_time ) {
+        ctime_val = localtime( &created );
+        memcpy( sigmeta->extended_info[sig_idx].creation_time,
+                ctime_val, sizeof( struct tm ) );
+      }
+
+      /* the extended signature verification status */
+      sumGPGME = gpgme_get_sig_ulong_attr( ctx,
+                                           sig_idx,
+                                           GPGME_ATTR_SIG_SUMMARY,
+                                           0 );
+      fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME );
+      // translate GPGME status flags to common CryptPlug status flags
+      sumPlug = 0;
+      if( sumGPGME & GPGME_SIGSUM_VALID       ) sumPlug |= SigStat_VALID      ;
+      if( sumGPGME & GPGME_SIGSUM_GREEN       ) sumPlug |= SigStat_GREEN      ;
+      if( sumGPGME & GPGME_SIGSUM_RED         ) sumPlug |= SigStat_RED        ;
+      if( sumGPGME & GPGME_SIGSUM_KEY_REVOKED ) sumPlug |= SigStat_KEY_REVOKED;
+      if( sumGPGME & GPGME_SIGSUM_KEY_EXPIRED ) sumPlug |= SigStat_KEY_EXPIRED;
+      if( sumGPGME & GPGME_SIGSUM_SIG_EXPIRED ) sumPlug |= SigStat_SIG_EXPIRED;
+      if( sumGPGME & GPGME_SIGSUM_KEY_MISSING ) sumPlug |= SigStat_KEY_MISSING;
+      if( sumGPGME & GPGME_SIGSUM_CRL_MISSING ) sumPlug |= SigStat_CRL_MISSING;
+      if( sumGPGME & GPGME_SIGSUM_CRL_TOO_OLD ) sumPlug |= SigStat_CRL_TOO_OLD;
+      if( sumGPGME & GPGME_SIGSUM_BAD_POLICY  ) sumPlug |= SigStat_BAD_POLICY ;
+      if( sumGPGME & GPGME_SIGSUM_SYS_ERROR   ) sumPlug |= SigStat_SYS_ERROR  ;
+      if( !sumPlug )
+        sumPlug = SigStat_NUMERICAL_CODE | sumGPGME;
+      sigmeta->extended_info[sig_idx].sigStatusFlags = sumPlug;
+
+      sigmeta->extended_info[sig_idx].validity = GPGME_VALIDITY_UNKNOWN;
+
+      err = gpgme_get_sig_key (ctx, sig_idx, &key);
+
+      if ( err == GPGME_No_Error) {
+        const char* attr_string;
+        unsigned long attr_ulong;
+
+        /* extract key identidy */
+        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_KEYID, 0, 0);
+        if (attr_string != 0)
+            storeNewCharPtr( &sigmeta->extended_info[sig_idx].keyid, attr_string );
+
+        /* extract finger print */
+        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_FPR, 0, 0);
+        if (attr_string != 0)
+            storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint,
+                            attr_string );
+
+        /* algorithms useable with this key */
+        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_ALGO, 0, 0);
+        if (attr_string != 0)
+            storeNewCharPtr( &sigmeta->extended_info[sig_idx].algo,
+                            attr_string );
+        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_ALGO, 0, 0);
+        sigmeta->extended_info[sig_idx].algo_num = attr_ulong;
+
+        /* extract key validity */
+        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_VALIDITY, 0, 0);
+        sigmeta->extended_info[sig_idx].validity = attr_ulong;
+
+        /* extract user id, according to the documentation it's representable
+        * as a number, but it seems that it also has a string representation
+        */
+        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, 0, 0);
+        if (attr_string != 0) {
+            a = parse_dn( attr_string );
+            dn = reorder_dn( a );
+            storeNewCharPtr( &sigmeta->extended_info[sig_idx].userid,
+                             dn );
+        }
+        
+        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_USERID, 0, 0);
+        sigmeta->extended_info[sig_idx].userid_num = attr_ulong;
+
+        /* extract the length */
+        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_LEN, 0, 0);
+        sigmeta->extended_info[sig_idx].keylen = attr_ulong;
+
+        /* extract the creation time of the key */
+        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_CREATED, 0, 0);
+        sigmeta->extended_info[sig_idx].key_created = attr_ulong;
+
+        /* extract the expiration time of the key */
+        attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_EXPIRE, 0, 0);
+        sigmeta->extended_info[sig_idx].key_expires = attr_ulong;
+
+        /* extract user name */
+        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_NAME, 0, 0);
+        if (attr_string != 0) {
+            a = parse_dn( attr_string );
+            dn = reorder_dn( a );
+            storeNewCharPtr( &sigmeta->extended_info[sig_idx].name,
+                             dn );
+        }
+
+        /* extract email(s) */
+        sigmeta->extended_info[sig_idx].emailCount = 0;
+        sigmeta->extended_info[sig_idx].emailList = 0;
+        for( UID_idx=0; 
+             (attr_string = gpgme_key_get_string_attr(key,
+                              GPGME_ATTR_EMAIL, 0, UID_idx)); 
+             ++UID_idx ){
+          if (*attr_string) {
+            fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string );
+            if( sigmeta->extended_info[sig_idx].emailCount )
+                alloc_return = 
+                    malloc( sizeof( char*) );
+            else
+                alloc_return = 
+                    realloc( sigmeta->extended_info[sig_idx].emailList,
+                             sizeof( char*)
+                             * (sigmeta->extended_info[sig_idx].emailCount + 1) );
+            if( alloc_return ) {
+              sigmeta->extended_info[sig_idx].emailList = alloc_return;
+              storeNewCharPtr( 
+                  &( sigmeta->extended_info[sig_idx].emailList[
+                          sigmeta->extended_info[sig_idx].emailCount ] ),
+                  attr_string );
+              ++sigmeta->extended_info[sig_idx].emailCount;
+            }
+          }
+        }
+        if( !sigmeta->extended_info[sig_idx].emailCount )
+          fprintf( stderr, "gpgmeplug checkMessageSignature found NO EMAIL\n" );
+
+        /* extract the comment */
+        attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_COMMENT, 0, 0);
+        if (attr_string != 0)
+            storeNewCharPtr( &sigmeta->extended_info[sig_idx].comment,
+                            attr_string );
+      }
+      else
+        storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint, fpr );
+
+      sig_status = sig_status_to_string( status );
+      storeNewCharPtr( &sigmeta->extended_info[sig_idx].status_text,
+                       sig_status );
+
+    } else
+      break; /* if allocation fails once, it isn't likely to
+                succeed the next time either */
+
+    fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created);
+  }
+  sigmeta->extended_info_count = sig_idx;
+  sigmeta->nota_xml = gpgme_get_notation( ctx );
+  sigmeta->status_code = status;
+
+  gpgme_release( ctx );
+  return ( status == GPGME_SIG_STAT_GOOD );
+}
+