Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Initial import

  • Loading branch information...
commit e59deea0fc6fa59e366a71e5150dd9c7799921b3 0 parents
Cory Wright authored September 29, 2009
15  INSTALL
... ...
@@ -0,0 +1,15 @@
  1
+Written by Cory Wright - cwright /at/ standblue.net 
  2
+
  3
+To install quser just unpack the tarball, cd into the quser src 
  4
+directory, and do the normal make and  make install routine.
  5
+
  6
+  tar xzf quser-0.8.tar.gz
  7
+  cd quser-0.8
  8
+  make
  9
+  make test (optional)
  10
+  sudo make install
  11
+
  12
+cmaildir will be installed in /usr/local/bin/ while validate-sender,
  13
+validate-recipient, mybadmailto, and mybadmailfrom will be installed 
  14
+in /var/qmail/bin/ . If you don't like this then just change the 
  15
+Makefile, but I feel that these are the best places for these programs.
36  Makefile
... ...
@@ -0,0 +1,36 @@
  1
+# $Id: Makefile,v 1.8 2002/10/01 04:46:56 cwright Exp $
  2
+
  3
+all: validate-sender validate-recipient mybadmailfrom mybadrcptto cmaildir
  4
+
  5
+validate-sender: validate.c quser.o
  6
+	gcc -Wall -DSENDER -o validate-sender quser.o validate.c
  7
+
  8
+validate-recipient: validate.c quser.o
  9
+	gcc -Wall -DRECIPIENT -o validate-recipient quser.o validate.c
  10
+
  11
+mybadmailfrom: mybadenvelope.c quser.o
  12
+	gcc -Wall -DMAILFROM -o mybadmailfrom quser.o mybadenvelope.c
  13
+
  14
+mybadrcptto: mybadenvelope.c quser.o
  15
+	gcc -Wall -DRCPTTO -o mybadrcptto quser.o mybadenvelope.c
  16
+
  17
+cmaildir: cmaildir.c quser.o
  18
+	gcc -o cmaildir quser.o cmaildir.c
  19
+
  20
+quser.o: quser.c quser.h
  21
+	gcc -Wall -O1 -c quser.c
  22
+
  23
+install: validate-sender validate-recipient \
  24
+	mybadmailfrom mybadrcptto cmaildir
  25
+	/usr/bin/install -s -g qmail -c validate-sender /var/qmail/bin/
  26
+	/usr/bin/install -s -g qmail -c validate-recipient /var/qmail/bin/
  27
+	/usr/bin/install -s -g qmail -c mybadmailfrom /var/qmail/bin/
  28
+	/usr/bin/install -s -g qmail -c mybadrcptto /var/qmail/bin/
  29
+	/usr/bin/install -s -c cmaildir /usr/local/bin/
  30
+
  31
+clean:
  32
+	rm -f core validate-sender validate-recipient mybadmailfrom \
  33
+	mybadrcptto cmaildir quser.o
  34
+
  35
+test: validate-sender validate-recipient mybadmailfrom mybadrcptto test.sh
  36
+	bash test.sh
116  README
... ...
@@ -0,0 +1,116 @@
  1
+Written by Cory Wright - cwright /at/ standblue.net
  2
+
  3
+You can find the most up to date documentation online at 
  4
+http://projects.standblue.net/software/quser/index.moto
  5
+
  6
+Tools included with quser.
  7
+
  8
+* cmaildir
  9
+* validate-sender
  10
+* validate-recipient
  11
+* mybadmailfrom
  12
+* mybadmailto
  13
+
  14
+
  15
+cmaildir is a short C program for checking Maildir's for 
  16
+new mail. If run with no arguments cmaildir checks ~/Maildir/ 
  17
+for new mail and also reports messages in the inbox. If 
  18
+arguments are passed to cmaildir then it expects them to be 
  19
+paths to Maildir style directories, but do not include the 
  20
+/cur/ and /new/ portions, the Maildir is the set together. 
  21
+I wrote cmaildir because I use Courier-IMAP and it uses 
  22
+Maildirs for its folders. I have my list addresses setup to 
  23
+go straight into my IMAP folders so with cmaildir I can run 
  24
+the following to get a status of all my folders 
  25
+(including ~/Maildir/):
  26
+
  27
+  shell$ cmaildir ~/Maildir/.Lists.qmail/ ~/Maildir/.Lists.moto/
  28
+  You have 6 new messages, 37 saved
  29
+
  30
+While this may not be that convenient to type at a command 
  31
+line, its most useful in a .bash_profile file or as a bash 
  32
+alias.
  33
+
  34
+
  35
+
  36
+validate-sender is a little C program I wrote because I needed 
  37
+to check a sender against a list before allowing it to post to 
  38
+an address. I had setup an address for people to add addresses 
  39
+to badmailfrom but only wanted certain users to be able to have 
  40
+this ability. validate-sender is designed to be called from a 
  41
+.qmail file after bouncesaying or condredirect. It takes the 
  42
+filename of the list file as an argument. The list file should 
  43
+contain a list of addresses or domains, one per line. Domain 
  44
+entries can either be in the form @site.dom or site.dom. For 
  45
+example:
  46
+
  47
+  |bouncesaying "You are not in my list of allowed senders" validate-sender /etc/badmailadders
  48
+  |/usr/local/bin/addtobadmailfrom
  49
+
  50
+Or, with condredirect to alert me when somebody tries to submit:
  51
+
  52
+  |condredirect myemailaddress validate-sender /etc/badmailadders
  53
+  |/usr/local/bin/addtobadmailfrom
  54
+
  55
+validate-sender returns 1 if a match is found, and 0 if no match 
  56
+is found. 111 is returned if there is an error. I stick validate-sender 
  57
+in /var/qmail/bin since the only place it will probably ever be 
  58
+used is with qmail. 
  59
+
  60
+Please note that no method is fool proof against forgeries, 
  61
+just see what djb has to say. In other words, dont trust your 
  62
+system to anything like this, it should only be used for trivial 
  63
+checks.
  64
+
  65
+
  66
+The validate-recipient program is very similar to the validate-sender
  67
+program, except it checks against the value of the SMTP envelope recipient 
  68
+address. This is mainly for use in .qmail-default files. For example, if 
  69
+all of your mail passes through a mail gateway that forwards mail using 
  70
+smtproutes then you probably use a .qmail-default file for this. If you 
  71
+know in advance the complete list of addresses that should be forwarded 
  72
+then you can block anything else from being forwarded.
  73
+
  74
+
  75
+  |bouncesaying "No mailbox by that name." validate-recipient /path/to/addresses.txt
  76
+  |forward "$DEFAULT"@someotherserver.example.com
  77
+
  78
+
  79
+validate-recipient uses the same exit codes as validate-sender. 
  80
+
  81
+mybadmailfrom is a program that allows individual users to manage 
  82
+their own badmailfrom lists. If a user is sick of getting mail from 
  83
+a certain address or domain then all they need to do is add it to 
  84
+their personal badmailfrom list. Once the list is ready the user can 
  85
+add a line to their .qmail file before all the rest:
  86
+
  87
+  |mybadmailfrom ~/Maildir/mybadmailfrom
  88
+  ./Maildir/
  89
+
  90
+Although messages from addresses listed in ~/Maildir/mybadmailfrom will
  91
+bounce, I should note that this works in a very different way from the 
  92
+badmailfrom file that qmail-smtpd uses. Addresses listed in 
  93
+/var/qmail/control/badmailfrom are blocked at the SMTP connection. 
  94
+Addresses listed in mybadmailfrom must first be accepted into the 
  95
+system so that qmail-local can run the .qmail file.
  96
+
  97
+
  98
+mybadrcptto is useful for blocking certain recipient addresses in a 
  99
+.qmail-default file. For example, if you have a qmail gateway that scans 
  100
+all mail for spam or viruses and forwards accepted mail onto another server, 
  101
+you may want to block certain invalid or expired addresses. The badmailrcpto 
  102
+program will allow you to maintain a list of addresses that you dont want to 
  103
+pass through:
  104
+
  105
+  |mybadrcptto ~/ex-employees.txt
  106
+  |forward "$DEFAULT"@internal.example.com
  107
+
  108
+With this setup any mail sent to an address thats listed in the 
  109
+~/ex-employees.txt file will bounce. All other mail will pass through 
  110
+and be forwarded to the internal server. There is a patch available for 
  111
+qmail that will block certain RCPT TO: addresses at the SMTP conversation. 
  112
+The advantage to using mybadrcptto is that 1) you do not need to patch qmail, 
  113
+and 2) individual users can implement their own badrcptto lists. The 
  114
+disadvantage to using the mybadrcptto program as opposed to the patch is 
  115
+that all email must first be accepted into the system, and only then can 
  116
+qmail-local run the mybadrcptto program to check the recipient.
6  SECURITY
... ...
@@ -0,0 +1,6 @@
  1
+The validate-sender program (as well as the mybadmailfrom program)
  2
+only checks the SENDER environment variable.  This variable is set
  3
+by qmail-command using the value of MAIL FROM: from the SMTP 
  4
+conversation.  This can easily be forged, so you should not trust
  5
+anything mission critical to the validate-sender program.  It is
  6
+only meant to help with trivial checks.
6  addylist
... ...
@@ -0,0 +1,6 @@
  1
+a@b.com
  2
+@c.com
  3
+d.com
  4
+E@F.COM
  5
+f@G.COM
  6
+G@h.com
62  cmaildir.c
... ...
@@ -0,0 +1,62 @@
  1
+/*******************************************************************************
  2
+ *                                                                             *
  3
+ * This file is part of quser.   http://projects.standblue.net/software/quser  *
  4
+ *                                                                             *
  5
+ * $Id: cmaildir.c,v 1.4 2002/09/30 15:04:48 cwright Exp $                     *
  6
+ *                                                                             *
  7
+ ******************************************************************************/
  8
+
  9
+#include <stdio.h>
  10
+#include <string.h>
  11
+#include <stdlib.h>
  12
+#include "quser.h"
  13
+
  14
+int main(int argc, char **argv) { 
  15
+
  16
+  char *newdir=NULL;
  17
+  char *curdir=NULL;
  18
+  char *home=NULL;
  19
+  char *homemaildir=NULL;
  20
+  int strsize=0;
  21
+  int newmessages=0;
  22
+  int curmessages=0;
  23
+  int tnew,tcur;
  24
+
  25
+  if(argc == 1) {
  26
+    if((home=getenv("HOME")) == NULL) {
  27
+      fprintf(stderr,"cmaildir: $HOME is undefined\n");
  28
+      exit(1);
  29
+    }
  30
+    strsize=(strlen(home)*sizeof(char))+9;
  31
+    homemaildir=malloc(strsize);
  32
+    sprintf(homemaildir,"%s%s",home,"/Maildir");
  33
+    *argv = homemaildir;
  34
+  } else {
  35
+    *argv++;
  36
+  }
  37
+
  38
+  while(*argv != NULL) {
  39
+    strsize=(strlen(*argv)*sizeof(char))+6;
  40
+    newdir=malloc(strsize);
  41
+    curdir=malloc(strsize);
  42
+    sprintf(newdir,"%s%s",*argv,"/new/");
  43
+    sprintf(curdir,"%s%s",*argv,"/cur/");
  44
+    tnew = getMessages(newdir);
  45
+    tcur = getMessages(curdir);
  46
+    newmessages += (tnew > 0) ? tnew : 0;
  47
+    curmessages += (tcur > 0) ? tcur : 0;
  48
+    free(newdir);
  49
+    free(curdir);
  50
+    *argv++;
  51
+  }
  52
+
  53
+  printf("You have ");
  54
+  if(newmessages > 0)
  55
+    printf("\033[1;32m%i\033[m",newmessages);
  56
+  else
  57
+    printf("%i",newmessages);
  58
+
  59
+  printf(" new messages, %i saved\n",curmessages);
  60
+  return 0;
  61
+
  62
+}
55  mybadenvelope.c
... ...
@@ -0,0 +1,55 @@
  1
+/*******************************************************************************
  2
+ *                                                                             *
  3
+ * This file is part of quser.   http://projects.standblue.net/software/quser  *
  4
+ *                                                                             *
  5
+ * $Id: mybadenvelope.c,v 1.1 2002/10/01 04:01:20 cwright Exp $                *
  6
+ *                                                                             *
  7
+ ******************************************************************************/
  8
+
  9
+#include <stdio.h>
  10
+#include <stdlib.h>
  11
+#include <string.h>
  12
+#include "quser.h"
  13
+
  14
+#ifdef MAILFROM
  15
+ #define QUSERPROG "mybadmailfrom"
  16
+ #define ENVVAR "SENDER"
  17
+#endif
  18
+
  19
+#ifdef RCPTTO
  20
+ #define QUSERPROG "mybadrcptto"
  21
+ #define ENVVAR "RECIPIENT"
  22
+#endif
  23
+
  24
+int main(int argc, char **argv) {
  25
+  FILE *fp;
  26
+  char match[MAX_ADDRESS];
  27
+  char *address;
  28
+  int accept=1;
  29
+
  30
+  if(argc < 2) {
  31
+    fprintf(stderr,"%s: No address file given",QUSERPROG);
  32
+    exit(100);
  33
+  }
  34
+
  35
+  if((address=getenv(ENVVAR))==NULL) {
  36
+    fprintf(stderr,"%s: No %s set",QUSERPROG,ENVVAR);
  37
+    exit(100);
  38
+  }
  39
+
  40
+  if((fp=fopen(*++argv,"r"))==NULL) {
  41
+    fprintf(stderr,"%s: Could not open %s",QUSERPROG,*argv);
  42
+    exit(111);
  43
+  }
  44
+
  45
+  while(fgets(match,MAX_ADDRESS,fp)) {
  46
+    if(addressmatch(address,match)) {
  47
+      accept=0;
  48
+      break;
  49
+    }
  50
+  }
  51
+  fclose(fp);
  52
+
  53
+  return (accept==1) ? 0 : 100;
  54
+
  55
+}
60  quser.c
... ...
@@ -0,0 +1,60 @@
  1
+/*******************************************************************************
  2
+ *                                                                             *
  3
+ * This file is part of quser.                                                 *
  4
+ *                                                                             *
  5
+ * $Id: quser.c,v 1.4 2002/09/30 13:43:15 cwright Exp $                        *
  6
+ *                                                                             *
  7
+ ******************************************************************************/
  8
+
  9
+#include <stdio.h>
  10
+#include <stdlib.h>
  11
+#include <string.h>
  12
+#include <ctype.h>
  13
+#include <dirent.h>
  14
+#include "quser.h"
  15
+
  16
+int addressmatch(char *sender, char match[MAX_ADDRESS]) {
  17
+  char *endofline;
  18
+  char *senderdomain;
  19
+  int matches=0;
  20
+  int i=0;
  21
+  int j=0;
  22
+
  23
+  for(i=0;i<sizeof(sender);i++) sender[i] = tolower(sender[i]);
  24
+  for(j=0;j<sizeof(match);j++) match[j] = tolower(match[j]);
  25
+  printf("s:%s, m:%s\n",sender,match);
  26
+
  27
+  endofline=(strchr(match,'\n'));
  28
+  if(endofline!=NULL) *endofline='\0';
  29
+  if(strcmp(sender,match) == 0) {
  30
+    matches=1;
  31
+  } else {
  32
+    if(match[0]=='@') match++;
  33
+    if(strchr(match,'@')==NULL) {
  34
+      if((senderdomain=strrchr(sender,'@'))!=NULL) {
  35
+	if(strcmp(++senderdomain,match) == 0) {
  36
+	  matches=1;
  37
+	}
  38
+      }
  39
+    }
  40
+  }
  41
+  return (matches==0) ? 0 : 1;
  42
+}
  43
+
  44
+int getMessages(char *fldr) {
  45
+
  46
+  DIR *dir;
  47
+  struct dirent *entry;
  48
+  int mesg = 0;
  49
+
  50
+  if((dir = opendir(fldr)) != NULL) {
  51
+    while((entry = readdir(dir)) != NULL)
  52
+      if((entry->d_name)[0] != '.') ++mesg;
  53
+    closedir(dir);
  54
+  } else {
  55
+    fprintf(stderr,"cmaildir: cannot open dir: %s\n",fldr);
  56
+    mesg = -1;
  57
+  }
  58
+
  59
+  return mesg;
  60
+}
17  quser.h
... ...
@@ -0,0 +1,17 @@
  1
+/*******************************************************************************
  2
+ *                                                                             *
  3
+ * This file is part of quser.                                                 *
  4
+ *                                                                             *
  5
+ * $Id: quser.h,v 1.4 2002/09/30 13:43:15 cwright Exp $                        *
  6
+ *                                                                             *
  7
+ ******************************************************************************/
  8
+
  9
+#ifndef QUSER_H
  10
+#define QUSER_H
  11
+
  12
+#define MAX_ADDRESS 1024
  13
+
  14
+int addressmatch(char *sender, char match[100]);
  15
+int getMessages(char *fldr);
  16
+
  17
+#endif
157  test.sh
... ...
@@ -0,0 +1,157 @@
  1
+#!/bin/sh
  2
+
  3
+echo '$Id: test.sh,v 1.5 2002/10/01 04:01:20 cwright Exp $'
  4
+echo
  5
+
  6
+total=$((0))
  7
+passed=$((0))
  8
+failed=$((0))
  9
+
  10
+chret() {
  11
+    should=$1
  12
+    actual=$2
  13
+    shift
  14
+    shift
  15
+    echo
  16
+    total=$(($total+1))
  17
+    echo -n "Should return $should: "
  18
+    if [ "$should" = "$actual" ]; then
  19
+	passed=$((passed+1))
  20
+	echo "Passed"
  21
+    else
  22
+	failed=$((failed+1))
  23
+	echo "Failed ($actual)"
  24
+    fi
  25
+    echo
  26
+}
  27
+
  28
+echo " * Testing the validate-sender program"
  29
+echo
  30
+
  31
+echo "Testing empty \$SENDER"
  32
+./validate-sender list
  33
+chret "0" $?
  34
+
  35
+echo "Testing with no parameters"
  36
+env SENDER="a@b.com" ./validate-sender
  37
+chret "0" $?
  38
+
  39
+echo "Testing nonexistant file"
  40
+env SENDER="a@b.com" ./validate-sender nolist
  41
+chret "111" $?
  42
+
  43
+echo "Testing a@a.com"
  44
+env SENDER="a@a.com" ./validate-sender addylist
  45
+chret "0" $?
  46
+
  47
+echo "Testing a@b.com"
  48
+env SENDER="a@b.com" ./validate-sender addylist
  49
+chret "1" $?
  50
+
  51
+echo "Testing a@c.com"
  52
+env SENDER="a@c.com" ./validate-sender addylist
  53
+chret "1" $?
  54
+
  55
+echo "Testing a@d.com"
  56
+env SENDER="a@d.com" ./validate-sender addylist
  57
+chret "1" $?
  58
+
  59
+echo " * Testing the validate-recipient program"
  60
+echo
  61
+
  62
+echo "Testing empty \$RECIPIENT"
  63
+./validate-recipient list
  64
+chret "0" $?
  65
+
  66
+echo "Testing with no parameters"
  67
+env RECIPIENT="a@b.com" ./validate-recipient
  68
+chret "0" $?
  69
+
  70
+echo "Testing nonexistant file"
  71
+env RECIPIENT="a@b.com" ./validate-recipient nolist
  72
+chret "111" $?
  73
+
  74
+echo "Testing a@a.com"
  75
+env RECIPIENT="a@a.com" ./validate-recipient addylist
  76
+chret "0" $?
  77
+
  78
+echo "Testing a@b.com"
  79
+env RECIPIENT="a@b.com" ./validate-recipient addylist
  80
+chret "1" $?
  81
+
  82
+echo "Testing a@c.com"
  83
+env RECIPIENT="a@c.com" ./validate-recipient addylist
  84
+chret "1" $?
  85
+
  86
+echo "Testing a@d.com"
  87
+env RECIPIENT="a@d.com" ./validate-recipient addylist
  88
+chret "1" $?
  89
+
  90
+echo " * Testing the mybadmailfrom program"
  91
+echo 
  92
+
  93
+echo "Testing empty \$SENDER"
  94
+./mybadmailfrom list
  95
+chret "100" $?
  96
+
  97
+echo "Testing with no parameters"
  98
+env SENDER="a@b.com" ./mybadmailfrom
  99
+chret "100" $?
  100
+
  101
+echo "Testing nonexistant file"
  102
+env SENDER="a@b.com" ./mybadmailfrom nolist
  103
+chret "111" $?
  104
+
  105
+echo "Testing a@a.com"
  106
+env SENDER="a@a.com" ./mybadmailfrom addylist
  107
+chret "0" $?
  108
+
  109
+echo "Testing a@b.com"
  110
+env SENDER="a@b.com" ./mybadmailfrom addylist
  111
+chret "100" $?
  112
+
  113
+echo "Testing a@c.com"
  114
+env SENDER="a@c.com" ./mybadmailfrom addylist
  115
+chret "100" $?
  116
+
  117
+echo "Testing a@d.com"
  118
+env SENDER="a@d.com" ./mybadmailfrom addylist
  119
+chret "100" $?
  120
+
  121
+echo " * Testing the mybadrcptto program"
  122
+echo 
  123
+
  124
+echo "Testing empty \$RECIPIENT"
  125
+./mybadrcptto list
  126
+chret "100" $?
  127
+
  128
+echo "Testing with no parameters"
  129
+env RECIPIENT="a@b.com" ./mybadrcptto
  130
+chret "100" $?
  131
+
  132
+echo "Testing nonexistant file"
  133
+env RECIPIENT="a@b.com" ./mybadrcptto nolist
  134
+chret "111" $?
  135
+
  136
+echo "Testing a@a.com"
  137
+env RECIPIENT="a@a.com" ./mybadrcptto addylist
  138
+chret "0" $?
  139
+
  140
+echo "Testing a@b.com"
  141
+env RECIPIENT="a@b.com" ./mybadrcptto addylist
  142
+chret "100" $?
  143
+
  144
+echo "Testing a@c.com"
  145
+env RECIPIENT="a@c.com" ./mybadrcptto addylist
  146
+chret "100" $?
  147
+
  148
+echo "Testing a@d.com"
  149
+env RECIPIENT="a@d.com" ./mybadrcptto addylist
  150
+chret "100" $?
  151
+
  152
+
  153
+
  154
+echo " * Results *"
  155
+echo " Tests Taken:  $(($total-0))"
  156
+echo " Tests Passed: $(($passed-0))"
  157
+echo " Tests Failed: $(($failed-0))"
58  validate.c
... ...
@@ -0,0 +1,58 @@
  1
+/*******************************************************************************
  2
+ *                                                                             *
  3
+ * This file is part of quser.   http://projects.standblue.net/software/quser  *
  4
+ *                                                                             *
  5
+ * $Id: validate.c,v 1.2 2002/10/01 01:22:19 cwright Exp $                     *
  6
+ *                                                                             *
  7
+ ******************************************************************************/
  8
+
  9
+#include <stdio.h>
  10
+#include <stdlib.h>
  11
+#include <string.h>
  12
+#include "quser.h"
  13
+
  14
+#ifdef SENDER
  15
+ #define QUSERPROG "validate-sender"
  16
+ #define ENVVAR "SENDER"
  17
+#endif
  18
+
  19
+#ifdef RECIPIENT
  20
+ #define QUSERPROG "validate-recipient"
  21
+ #define ENVVAR "RECIPIENT"
  22
+#endif
  23
+
  24
+int main(int argc, char **argv) {
  25
+  FILE *fp;
  26
+  char match[MAX_ADDRESS];
  27
+  char *address;
  28
+  int accept=0;
  29
+
  30
+  if(argc < 2) {
  31
+    fprintf(stderr,"%s: No address list file given",QUSERPROG);
  32
+    exit(0);
  33
+  }
  34
+
  35
+  if((address=getenv(ENVVAR))==NULL) {
  36
+    fprintf(stderr,"%s: No %s set",QUSERPROG,ENVVAR);
  37
+    exit(0);
  38
+  }
  39
+
  40
+  if((fp=fopen(*++argv,"r"))==NULL) {
  41
+    fprintf(stderr,"%s: Could not open %s",QUSERPROG,*argv);
  42
+    exit(111);
  43
+  }
  44
+
  45
+  while(fgets(match,MAX_ADDRESS,fp)) {
  46
+    if(addressmatch(address,match)) {
  47
+      accept=1;
  48
+      break;
  49
+    }
  50
+  }
  51
+  fclose(fp);
  52
+
  53
+  /* output results to go into qmail logs */
  54
+  printf("%s: Found %smatch ",QUSERPROG,((accept==1)?"":"no "));
  55
+  printf("for address %s, %s",address,((accept==1)?"accepting.":"rejecting.  "));
  56
+  return (accept==1) ? 1 : 0;
  57
+
  58
+}

0 notes on commit e59deea

Please sign in to comment.
Something went wrong with that request. Please try again.