Index: /branches/rel_ag_9_4_5/aaa/Makefile
===================================================================
--- /branches/rel_ag_9_4_5/aaa/Makefile	(revision 20492)
+++ /branches/rel_ag_9_4_5/aaa/Makefile	(working copy)
@@ -19,7 +19,7 @@
 -I $(TOP)/lib/hash -I $(TOP)/feactl/include -I../fileshare/samba/include -I$(TOP)/include \
 -I $(TOP)/uproxy/utils/alwayson_logging/lib \
 -I$(TOP)/lib/muxconnapi -I$(TOP)/utils/vsite -I$(TOP)/uproxy/utils/libdriver -I./ -I/usr/local/include \
--I$(TOP)/ssl/openssl/include/ -I$(TOP)/ui/backend
+-I$(TOP)/ssl/openssl/include/ -I$(TOP)/ui/backend -I$(TOP)/localdb/jpeg
 
 #following definition of LDFLAGS is used to link but not compile
 LDFLAGS = -pthread -L ./libradius -lssl -lradius -L $(TOP)/objdir -lhash -lldap -llber -lan_process\
@@ -32,13 +32,15 @@
                            -L$(TOP)/license/lib -llicense \
                            -L$(TOP)/va/client -lva \
                            -L$(TOP)/aaa/lock_user -llock_user \
-                           -L $(TOP)/firewall/lib -lip -lkernelapi -L ./libsms -lsms -lstdc++ -L ./ -liconv -L ./libsmx -lSmxApiUnixAAA -lenglog -lfetch
+                           -L $(TOP)/firewall/lib -lip -lkernelapi -L ./libsms -lsms -lstdc++ -L ./ -liconv -L ./libsmx -lSmxApiUnixAAA -lenglog -lfetch \
+                           -L$(TOP)/localdb/libqrencode/.libs -lqrencode -Wl,-rpath,$(TOP)/localdb/libqrencode/.libs \
+                           -L$(TOP)/localdb/jpeg/.libs -ljpeg -Wl,-rpath,$(TOP)/localdb/jpeg/.libs
 
 # deleted LDFLAGS library compared with sp1:
 #                                   1, -L $(TOP)/objdir -lfastlog -lcompat -lcipher -lip  -lkernelapi -lvip 2,-liconv 3, -luserslog
-#                                   4, $(TOP)/lib/muxconnapi/libmuxconnapi.a 
-#                                   5, $(TOP)/lib/libznalloc/libznalloc.a 
-#                                   5, -L $(TOP)/lib/libc -lc -L $(TOP)/lib/libc_r -lc_r 
+#                                   4, $(TOP)/lib/muxconnapi/libmuxconnapi.a
+#                                   5, $(TOP)/lib/libznalloc/libznalloc.a
+#                                   5, -L $(TOP)/lib/libc -lc -L $(TOP)/lib/libc_r -lc_r
 
 #following operation compile and link object when running "make"
 
@@ -89,12 +91,12 @@
 buildsubdirs_ldapautosearch :
 	@for i in ${SDIR_LDAP_AUTOSEARCH} ; do echo `/bin/pwd`/$${i}; cd $${i}; \
 	make; cd ..; done
-	
+
 $(TARGET): aaad.o aaa_ldap.o aaa_radius.o aaa_common.o aaa_cli.o aaa_localdb.o aaa_cert.o aaa_sms.o aaa_smx.o sm3.o aaa_http.o lock_user.o
 	ln -sf ../lib/libiconv/libiconv.so.7 libiconv.so
-	$(CC) -o $@ $> $(LDFLAGS) 
-	
-$(IPC_LIB) : aaa_ipc.o	
+	$(CC) -o $@ $> $(LDFLAGS)
+
+$(IPC_LIB) : aaa_ipc.o
 	/usr/bin/ar rs $@ $>
 
 .c.o :
@@ -126,7 +128,7 @@
 
 SRCFILES=aaad.c aaa_ldap.c aaa_radius.c aaa_common.c aaa_ipc.c aaa_cli.c aaa_localdb.c aaa_cert.c aaa_sms.c aaa_smx.c sm3.c aaa_http.c lock_user.c
 
-INST_BIN=$(TARGET) sendmail_hardwareid.pl oauth_client.py oauth_monitor.sh
+INST_BIN=$(TARGET) sendmail_hardwareid.pl sendmail_qrcode.pl oauth_client.py oauth_monitor.sh
 INST_LIB=./libradius/libssl.so.5 ./libsmx/libSmxApiUnixAAA.so
 INST_CONF=./aaa_http_req_template
 #INST_CLI_LIB=
Index: /branches/rel_ag_9_4_5/aaa/sendmail_qrcode.pl
===================================================================
--- /branches/rel_ag_9_4_5/aaa/sendmail_qrcode.pl	(revision 0)
+++ /branches/rel_ag_9_4_5/aaa/sendmail_qrcode.pl	(working copy)
@@ -0,0 +1,56 @@
+#!/usr/bin/perl -w
+use strict;
+use MIME::Base64;
+
+my $sendmail = $ARGV[0];
+my $from     = "From: $ARGV[1]\n";
+my $to       = "TO: $ARGV[2]\n";
+my $subject  = "Subject: QRcode\n";
+my $qr_file  = $ARGV[3];
+my $boundary = "====BOUNDARY====";
+
+(my $filename = $qr_file) =~ s{.*/}{};
+
+# Read and base64 encode image
+open(my $img, '<', $qr_file) or die "Cannot open $qr_file: $!";
+binmode($img);
+my $img_data = do { local $/; <$img> };
+close($img);
+my $b64_img = encode_base64($img_data);
+
+# HTML content
+my $content = <<"END_HTML";
+<html>
+    <body>
+        <p>*** Please scan the OTP below.***</p>
+        <img src="cid:$filename">
+        <p>*************************************</p>
+    </body>
+</html>
+END_HTML
+
+# Send email
+open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!";
+print SENDMAIL $from;
+print SENDMAIL $to;
+print SENDMAIL $subject;
+print SENDMAIL "Content-type: multipart/related; boundary=\"$boundary\"\n\n";
+
+# Part 1: HTML
+print SENDMAIL "--$boundary\n";
+print SENDMAIL "Content-Type: text/html; charset=utf-8\n";
+print SENDMAIL "Content-Transfer-Encoding: 7bit\n\n";
+print SENDMAIL $content . "\n";
+
+# Part 2: Image
+print SENDMAIL "--$boundary\n";
+print SENDMAIL "Content-Type: image/jpg; name=\"$filename\"\n";
+print SENDMAIL "Content-Transfer-Encoding: base64\n";
+print SENDMAIL "Content-ID: <$filename>\n";
+print SENDMAIL "Content-Disposition: inline; filename=\"$filename\"\n\n";
+printf SENDMAIL $b64_img . "\n";
+
+# End boundary
+print SENDMAIL "--$boundary--\n";
+
+close(SENDMAIL);
Index: /branches/rel_ag_9_4_5/localdb/Makefile
===================================================================
--- /branches/rel_ag_9_4_5/localdb/Makefile	(revision 20492)
+++ /branches/rel_ag_9_4_5/localdb/Makefile	(working copy)
@@ -10,25 +10,44 @@
 POSTGRESQL_DIR=${PWD}/$(CA_ROOT)/localdb
 
 INST_LOCALDB_LIB=$(LDBLIB)/libldb.so $(LDBAPPS)/auth/libldb_auth.so $(POSTGRESQL_DIR)/pgsql/lib/libpq.so.5 $(POSTGRESQL_DIR)/pgsql/lib/libpq.so
-INST_LOCALDB_SERVER_LIB=$(LDBAPPS)/auth/server/libpg_auth_aaa.so $(LDBAPPS)/auth/server/libpg_trigger.so 
+INST_LOCALDB_SERVER_LIB=$(LDBAPPS)/auth/server/libpg_auth_aaa.so $(LDBAPPS)/auth/server/libpg_trigger.so
 INST_LOCALDB_UTILS=$(LDBUTILS)/func_auth.template.sql $(LDBUTILS)/view_auth.template.sql $(LDBUTILS)/build_template.pl \
                     $(LDBUTILS)/tbl_auth.template.sql  $(LDBUTILS)/trigger_auth.template.sql $(LDBUTILS)/postgres.sh \
                     $(LDBUTILS)/db_update.sh $(LDBUTILS)/postgresql.conf $(LDBUTILS)/ldb_autobackup.sh $(LDBUTILS)/hwid_sync.py $(LDBUTILS)/secret_sync.py
 INST_LOCALDB=ldb_build.sh
-all: postgresql-8.4.22 database_lib
+all: postgresql-8.4.22 libqrencode-3.2.0 jpegsrc-8 database_lib
 
 postgresql-8.4.22: postgresql-8.4.22.tar.gz
 	tar -zxf postgresql-8.4.22.tar.gz
 	ln -sf postgresql-8.4.22 postgresql
 	rm -rf $(POSTGRESQL_DIR)/pgsql
-	cd $(POSTGRESQL_DIR) && mkdir pgsql && cd ${PWD} 
+	cd $(POSTGRESQL_DIR) && mkdir pgsql && cd ${PWD}
 
-# compile postgresql-8.4.22 and install postgresql-8.4.22 
+# compile postgresql-8.4.22 and install postgresql-8.4.22
 # it will be installed to postgresql/pgsql
 	cd ./postgresql && \
 	./configure --prefix=$(POSTGRESQL_DIR)/pgsql --with-system-tzdata=/usr/share/zoneinfo && \
 	make && make install && cd ..
- 
+
+libqrencode-3.2.0: libqrencode-3.2.0.tar.gz
+	tar -zxf libqrencode-3.2.0.tar.gz
+	ln -sf libqrencode-3.2.0 libqrencode
+
+# compile libqrencode-3.2.0 and install libqrencode-3.2.0
+	cd ./libqrencode && \
+	sed -i.bak '/^[[:space:]]*AM_PATH_SDL/s/^/dnl /' configure.ac && \
+	sed -i.bak '/^[[:space:]]*if test x\$build_tools = xyes ; then/,/^[[:space:]]*fi/ s/^/dnl /' configure.ac && \
+	./autogen.sh && \
+	./configure --without-tools --prefix=$(POSTGRESQL_DIR) && \
+	make && make install && cd ..
+
+jpegsrc-8: jpegsrc.v8.tar.gz
+	tar -zxf jpegsrc.v8.tar.gz
+	ln -sf jpeg-8 jpeg
+	cd ./jpeg && \
+	./configure --prefix=$(POSTGRESQL_DIR) && \
+	make && make install && cd ..
+
 database_lib:
 # compile libldb (the fundamental library of LDB-API)
 # it will generate and install libldb.so to LDBROOT/dist/lib
@@ -51,5 +70,10 @@
 	rm -rf postgresql-8.4.22
 	rm -rf postgresql
 	rm -rf $(POSTGRESQL_DIR)/pgsql
+	rm -rf libqrencode-3.2.0
+	rm -rf libqrencode
+	rm -rf jpeg-8
+	rm -rf jpeg
+
 
 include $(TOP)/Makefile.install1
Index: /branches/rel_ag_9_4_5/localdb/apps/auth/Makefile
===================================================================
--- /branches/rel_ag_9_4_5/localdb/apps/auth/Makefile	(revision 20492)
+++ /branches/rel_ag_9_4_5/localdb/apps/auth/Makefile	(working copy)
@@ -3,30 +3,45 @@
 include $(LDBROOT)/Makefile.common
 SUB_DIR = dynamic_code
 
+QRDIR = $(TOP)/localdb/libqrencode
+QR_LIBFLAGS = -L$(QRDIR)/.libs -Wl,-rpath,$(QRDIR)/.libs -Wl,-rpath-link,$(QRDIR)/.libs
+
+JPEGDIR = $(TOP)/localdb/jpeg
+JPEG_LIBFLAGS = -L$(JPEGDIR)/.libs -Wl,-rpath,$(JPEGDIR)/.libs -Wl,-rpath-link,$(JPEGDIR)/.libs -ljpeg
+
 OBJECTS=auth_cli.o auth_aaa.o auth_sessmgrd.o
 HEADERS=$(LDBINC)/ldb_query.h $(LDBINC)/ldb_common.h \
 		$(LDBINC)/ldb_utils.h $(LDBINC)/ldb_mng.h $(LDBINC)/ldb_app_auth.h
 SRCFILES=auth_cli.c auth_aaa.c auth_sessmgrd.c
 
-all: SUB_MODULE libldb_auth.so  libpg_server
+all: SUB_MODULE libldb_auth.so libpg_server sendmail
 
 SUB_MODULE:
 	make -C $(SUB_DIR)
 
+sendmail.o: sendmail.c
+	cc -c -Wall -o sendmail.o sendmail.c
+
+sendmail: sendmail.o
+	cc -o sendmail sendmail.o
+	cp sendmail $(CA_ROOT)/bin
+	chmod 4755 $(CA_ROOT)/bin/sendmail
+	chown root $(CA_ROOT)/bin/sendmail
+
 $(OBJECTS):	$(SRCFILES) $(HEADERS)
-	cc -g -fPIC -DPIC -c -Wall -I$(TOP)/FreeBSD/src/sys/ -I$(PGINC) -I$(LDBINC) -I $(TOP)/license/include -I $(TOP)/include -I$(SUB_DIR) $(SRCFILES)
+	cc -g -fPIC -DPIC -c -Wall -I$(TOP)/FreeBSD/src/sys/ -I$(PGINC) -I$(LDBINC) -I$(TOP)/license/include -I$(TOP)/include -I$(SUB_DIR) -I$(QRDIR) -I$(JPEGDIR) -I$(TOP)/ui/backend $(SRCFILES)
 
 libldb_auth.so:	$(OBJECTS)
-	cc -g -shared -Wl,-soname,libldb_auth.so -o libldb_auth.so auth_cli.o auth_aaa.o auth_sessmgrd.o $(SUB_DIR)/libdc.a
+	cc -g -shared -Wl,-soname,libldb_auth.so -o libldb_auth.so auth_cli.o auth_aaa.o auth_sessmgrd.o $(SUB_DIR)/libdc.a $(QR_LIBFLAGS) -lqrencode $(JPEG_LIBFLAGS)
 
 auth_test: auth_test.c libldb_auth.so
 	cc -g -fPIC -DPIC -Wall -I$(PGINC) -I$(LDBINC) -L. -lldb_auth -L$(LDBLIB) -lldb -L$(PGLIB) -lpq -L$(TOP)/utils/vsite/ -lvsite -o auth_test auth_test.c
 
 libpg_server:
 	 cd ./server && make all && cd ..
-	
+
 clean:
 	make clean -C $(SUB_DIR)
-	rm -f auth_test *.so *.o
+	rm -f auth_test *.so *.o sendmail
 	cd ./server && make clean && cd ..
 
Index: /branches/rel_ag_9_4_5/localdb/apps/auth/auth_cli.c
===================================================================
--- /branches/rel_ag_9_4_5/localdb/apps/auth/auth_cli.c	(revision 20492)
+++ /branches/rel_ag_9_4_5/localdb/apps/auth/auth_cli.c	(working copy)
@@ -10,6 +10,7 @@
 
 */
 #include <sys/types.h>
+#include <sys/sysctl.h>
 #include <time.h>
 #include <dirent.h>
 #include <ldb_app_auth.h>
@@ -24,6 +25,13 @@
 #include "../../../FreeBSD/src/sys/click/app/vsite/sec_vsite.h"
 #include "../../../aaa/aaa_common.h"
 #include "../dynamic_code/secret.h"
+#include <qrencode.h>
+#include <jpeglib.h>
+#include <unistd.h>
+#include "sys_mail.h"
+#include <sys/stat.h>
+#include <sys/shm.h>
+#include <click/app/proxy/proxy_shm.h>
 
 ldba_auth_boundary_t ldba_auth_boundary_table[MAX_MODEL+1] = {
 	{0,0},
@@ -76,6 +84,96 @@
 	return saa_hide_site;
 }
 
+int qr_to_file(char *site, char *username, unsigned char *image, int width) {
+	char jpg_path[256];
+	snprintf(jpg_path, sizeof(jpg_path), "/ca/conf/vsites/%s/qrcode/qrcode_%s.jpg", site, username);
+
+	FILE *jpg = fopen(jpg_path, "wb");
+	if (!jpg) {
+        ldb_englog(__FUNCTION__, "Failed to open jpg file.");
+        fclose(jpg);
+        return -1;
+	}
+
+	struct jpeg_compress_struct cinfo;
+	struct jpeg_error_mgr jerr;
+	cinfo.err = jpeg_std_error(&jerr);
+	jpeg_create_compress(&cinfo);
+	jpeg_stdio_dest(&cinfo, jpg);
+	cinfo.image_width = width;
+	cinfo.image_height = width;
+	cinfo.input_components = 3;
+	cinfo.in_color_space = JCS_RGB;
+	jpeg_set_defaults(&cinfo);
+	jpeg_set_quality(&cinfo, 95, TRUE);
+	jpeg_start_compress(&cinfo, TRUE);
+
+	while (cinfo.next_scanline < cinfo.image_height) {
+		JSAMPROW row_ptr = &image[cinfo.next_scanline * width * 3];
+		jpeg_write_scanlines(&cinfo, &row_ptr, 1);
+	}
+	jpeg_finish_compress(&cinfo);
+	jpeg_destroy_compress(&cinfo);
+
+	fclose(jpg);
+
+	return 0;
+}
+
+void generate_qrcode(char *site, char *username, char *secret_key) {
+	char path[128];
+	snprintf(path, sizeof(path), "/ca/conf/vsites/%s/qrcode", site);
+	if (mkdir(path, 0755) != 0) {
+		if (errno != EEXIST) {
+			ldb_englog(__FUNCTION__, "Failed to create qrcode dir.");
+			return;
+		}
+	}
+	ldb_englog(__FUNCTION__, "Qrcode dir created.");
+
+	char	otp_uri[256];
+	snprintf(otp_uri, sizeof(otp_uri), "otpauth://totp/%s:%s?secret=%s&digits=6&period=30", site, username, secret_key);
+
+	QRcode *qr = QRcode_encodeString(otp_uri, 0, QR_ECLEVEL_Q, QR_MODE_8, 1);
+    if (!qr) {
+		ldb_englog(__FUNCTION__, "Failed to encode QR code.");
+		return;
+	}
+
+	int scale = 5, margin = 1;
+	int width = (margin * 2 + qr->width) * scale;
+	unsigned char *image = malloc(width * width * 3);
+	if (!image) {
+		ldb_englog(__FUNCTION__, "Failed to allocate image.");
+		return;
+	}
+	memset(image, 0xFF, width * width * 3);
+
+	int i, j, di, dj;
+	for (j = 0; j < qr->width; j++) {
+		for (i = 0; i < qr->width; i++) {
+			unsigned char color = (qr->data[j * qr->width + i] & 0x01) ? 0x00 : 0xFF;
+			for (dj = 0; dj < scale; dj++) {
+				for (di = 0; di < scale; di++) {
+					int pos = ((margin + j) * scale + dj) * width + ((margin + i) * scale + di);
+					image[pos * 3 + 0] = color;
+					image[pos * 3 + 1] = color;
+					image[pos * 3 + 2] = color;
+				}
+			}
+		}
+	}
+	QRcode_free(qr);
+
+	/* save as jpg file */
+	if (qr_to_file(site, username, image, width)) {
+		ldb_englog(__FUNCTION__, "Failed to save jpg image.\n");
+		return;
+	}
+	free(image);
+	return;
+}
+
 /*---------- [ldba_auth_create_db] ----------
  * create a database with type "auth".
  * Input:
@@ -370,7 +468,7 @@
             {
                 strcpy(secret_key, custom_info2);
             }
-
+			generate_qrcode(dbname, username, secret_key);
 	    /* add a user with information to "v_acct" by sql command */
 	    result = ldbq_exec_one(conn, "INSERT INTO %s (user_name, user_passwd, phone, mail_address, nfs_group, nfs_account,"
 	                                                  " custom_info1, custom_info2, custom_info3, custom_info4, custom_info5,"
@@ -8058,3 +8156,152 @@
 
     return LDB_SUCCESS;
 }
+
+static sys_mail_conf_t *
+get_extern_mail_conf(void)
+{
+	int shm_id = 0;
+	static sys_mail_conf_t *conf_p = NULL;
+
+	if (conf_p != NULL) {
+		return conf_p;
+	}
+
+	shm_id = shmget(SYS_MAIL_SHM_KEY, 0, 0);
+	if (shm_id == -1) {
+		return NULL;
+	}
+
+	conf_p = (sys_mail_conf_t *)shmat(shm_id, NULL, 0);
+	if (conf_p == NULL) {
+		return NULL;
+	}
+
+	return conf_p;
+}
+
+#define SMS_MESSAGE_LEN_REAL (SMS_MESSAGE_LEN * 3 + 1)
+
+int ldb_send_qrcode_mail(char *address, char *filename)
+{
+	/*help variables*/
+	char str[MAX_LINE_SIZE+ 1] = "";
+	char hostname[MAX_LINE_SIZE + 1] = "";
+
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = get_extern_mail_conf();
+
+	if (!address || !address[0]) {
+		ldb_englog(__FUNCTION__, "address is empty");
+		return -1;
+	}
+
+	if (conf_p == NULL || !conf_p->extern_mail_on) {
+		/*get local host name, used as From: field in email*/
+		memset(hostname, 0, sizeof(hostname));
+		if (gethostname(hostname, sizeof(hostname) -1) < 0) {
+			ldb_englog(__FUNCTION__, "gethostname failed (%d)");
+		}
+
+		snprintf(str, MAX_LINE_SIZE, "/ca/bin/sendmail \"/ca/bin/sendmail_qrcode.pl '/usr/sbin/sendmail -t' 'admin@%s' '%s' '%s'\"",
+		         hostname, address, filename);
+	} else {
+		snprintf(str, MAX_LINE_SIZE, "/ca/bin/sendmail \"/ca/bin/sendmail_qrcode.pl '/ca/bin/ssmtp %s' '<%s>' '<%s>' '%s'\"",
+		         address, conf_p->mextern_server.user, address, filename);
+	}
+	ldb_englog(__FUNCTION__, "sent a qrcode email from (admin@%s) to (%s)", hostname, address);
+	ldb_englog(__FUNCTION__, "system (%s)", str);
+	system(str);
+	return 0;
+}
+
+int
+ldb_send_qrcode(char *dbname, char *username)
+{
+	ldb_conn_t   *conn;
+	ldb_result_t *result;
+	sec_vsite_t *vsite;
+	char condition[1024] = "";
+	char *email_p;
+	char *secret;
+	char secret_key[SEC_ENCODED_SECRET_LEN] = {'\0'};
+	int ret;
+
+	if (username && *username != '\0') {
+		sprintf(condition, "WHERE lower(user_name)=lower('%s')", username);
+	} else {
+		ldb_englog(__FUNCTION__, "The name of user is invalid.");
+	    return LDB_ERR_INVALID_PARAM;
+	}
+
+	/* connect to database */
+	conn = ldbq_connect(LDB_TYPE_AUTH, dbname);
+	if (conn == NULL) {
+	    ldb_englog(__FUNCTION__, "Fail to connect database: auth_%s", dbname);
+	    return LDB_ERR_FAIL_CONN;
+	}
+
+	if (strcmp(dbname, SAA_HIDDEN_VSNAME) == 0) {
+		vsite = get_saa_hide_site();
+	} else {
+		vsite = find_vsite_by_name(dbname);
+	}
+	if (vsite == NULL) {
+		ldb_englog(__FUNCTION__, "virtual site:%s not find\n", dbname);
+		return LDB_ERR_INVALID_PARAM;
+	}
+
+	if (FLAG_ISSET(vsite->aaa_configure->flag, AAA_FLAG_USERNAME_CASE_INSENSITIVE)) {
+		result = ldbq_exec_one(conn, "SELECT * FROM %s WHERE lower(user_name) = lower('%s');",
+			LDB_VIEW_AUTH_USER, username);
+	} else {
+		result = ldbq_exec_one(conn, "SELECT * FROM %s WHERE user_name = '%s';",
+			LDB_VIEW_AUTH_USER, username);
+	}
+
+	if (result == NULL) {
+		ldb_englog(__FUNCTION__, "Fail to execute SQL command: result is null.");
+	    ldbq_close_conn(conn);
+	    return LDB_ERR_FAIL_EXEC;
+	} else if (result->status != LDB_RES_SUCCESS) {
+		ldb_englog(__FUNCTION__, "Fail to execute select command.");
+		ldbq_clear_res(result);
+		ldbq_close_conn(conn);
+		return LDB_ERR_FAIL_EXEC;
+	} else if (result->size == 0 && username && *username != '\0') {
+		ldb_englog(__FUNCTION__, "Fail to find given account %s.", username);
+		ldbq_clear_res(result);
+		ldbq_close_conn(conn);
+		return LDB_FAILURE;
+	}
+
+	email_p = ldbq_get_value_by_name(result, 0, "mail_address");
+	if (!email_p || *email_p == '\0') {
+		ldb_englog(__FUNCTION__, "Cannot find mail address.");
+	    return LDB_ERR_EMPTY_RESULT;
+	}
+
+	char filepath[256];
+	snprintf(filepath, sizeof(filepath), "/ca/conf/vsites/%s/qrcode/qrcode_%s.jpg", dbname, username);
+	if (access(filepath, F_OK) != 0) {
+		ldb_englog(__FUNCTION__, "Cannot find qrcode image.");
+		secret = ldbq_get_value_by_name(result, 0, "custom_info2");
+		if (!secret || *secret == '\0') {
+			/* haven't been tested */
+			ldb_englog(__FUNCTION__, "Cannot find secret key.");
+			generate_secret_key(secret_key);
+			ldb_englog(__FUNCTION__, "Secret key generated.");
+			secret = secret_key;
+		}
+		generate_qrcode(dbname, username, secret);
+	}
+	ldbq_clear_res(result);
+	ldbq_close_conn(conn);
+
+	ret = ldb_send_qrcode_mail(email_p, filepath);
+	ldb_englog(__FUNCTION__, "QRcode otp email sent.");
+
+	return (ret == 0) ? LDB_SUCCESS : LDB_ERR_EXIST;
+}
+
Index: /branches/rel_ag_9_4_5/localdb/apps/auth/sendmail.c
===================================================================
--- /branches/rel_ag_9_4_5/localdb/apps/auth/sendmail.c	(revision 0)
+++ /branches/rel_ag_9_4_5/localdb/apps/auth/sendmail.c	(working copy)
@@ -0,0 +1,24 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* -----------------------------------------------------------------------------
+ * This file is used to support sending qrcode email otp to users as root
+ * -----------------------------------------------------------------------------
+ */
+
+int main(int argc, char** argv) {
+  if (argc != 2) {
+    fprintf(stderr, "Usage: %s \"<command_to_run_sendmail_qrcode>\"\n", argv[0]);
+    return -1;
+  }
+
+  if (setuid(0) != 0) {
+    perror("setuid");
+    return -1;
+  }
+
+  system(argv[1]);
+  return 0;
+}
Index: /branches/rel_ag_9_4_5/localdb/include/ldb_app_auth.h
===================================================================
--- /branches/rel_ag_9_4_5/localdb/include/ldb_app_auth.h	(revision 20492)
+++ /branches/rel_ag_9_4_5/localdb/include/ldb_app_auth.h	(working copy)
@@ -351,4 +351,5 @@
 int ldb_portal_bookmark_user(char *db_name, char *user_name, int i_type, char *url, char *desc, char *param);
 int ldb_no_portal_bookmark_user(char *db_name, char *user_name, int i_type, char *url);
 int ldb_clear_portal_bookmark_user(char *db_name, char *user_name, int i_type);
+int ldb_send_qrcode(char *dbname, char *username);
 
Index: /branches/rel_ag_9_4_5/ui/backend/Makefile
===================================================================
--- /branches/rel_ag_9_4_5/ui/backend/Makefile	(revision 20492)
+++ /branches/rel_ag_9_4_5/ui/backend/Makefile	(working copy)
@@ -15,6 +15,8 @@
 # This include a fake SLB library for testing.
 LIBS= $(LIBRARY) -L ../generator -lparser -lvip \
 	-lip -lkvm -lan_rpc_cli -lan_ipc -lcacli -lfastlog -lmpdconfig
+LIBS+= -L$(TOP)/localdb/libqrencode/.libs -lqrencode -Wl,-rpath,$(TOP)/localdb/libqrencode/.libs \
+	-L$(TOP)/localdb/jpeg/.libs -ljpeg -Wl,-rpath,$(TOP)/localdb/jpeg/.libs
 
 #Ticket-SmartDNS: link with sdns cli lib
 LIBS+=	-lgenlog -lcrypt -lcurses -lm \
@@ -91,15 +93,16 @@
 	-I$(TOP)/uproxy/http_proxy/smanager \
 	-I$(TOP)/uproxy/http_proxy \
 	-I$(TOP)/uproxy/utils/common \
-	-I$(TOP)/ha/halib
+	-I$(TOP)/ha/halib \
+	-I$(TOP)/localdb/jpeg
 
 all: uiheaders backend recovery
 
-backend: $(OBJS) $(CLI_LIB) 
+backend: $(OBJS) $(CLI_LIB)
 	$(CC) $(FLAGS) -o $@ $(OBJS) $(LIBS) $(DEFINES)
 
-recovery: $(ROBJS) 
-	$(CC) $(FLAGS) -g -o $@ $(ROBJS) -L$(LIBRARY) -lkernelapi -lui_output -lcrypto $(DEFINES) 
+recovery: $(ROBJS)
+	$(CC) $(FLAGS) -g -o $@ $(ROBJS) -L$(LIBRARY) -lkernelapi -lui_output -lcrypto $(DEFINES)
 
 quickb:
 	$(RM) -rf $(TOP)/ui/backend/*.o
Index: /branches/rel_ag_9_4_5/ui/generator/commands.pm
===================================================================
--- /branches/rel_ag_9_4_5/ui/generator/commands.pm	(revision 20492)
+++ /branches/rel_ag_9_4_5/ui/generator/commands.pm	(working copy)
@@ -50518,7 +50518,6 @@
 			}
 		],
 	},
-	
 	{
 		obj_type => "ITEM",
 		name => "group",
@@ -50715,6 +50714,38 @@
 						},
 		],
 	},
+	{
+		obj_type => "ITEM",
+		name => "qrcode",
+		menu => "root_localdb",
+		module => "localdb",
+		help_string => "send a qrcode OTP email to the user",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_LOCAL|CMD_SCOPE_VIRTUAL|CMD_SITE_EXCLUSIVE|CMD_SITE_ALIAS",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "localdb_sendqr",
+		function_args => [{
+								type => "STRING",
+								name => "vsite",
+								help_string => "vsite name",
+								arg_attribute => "SITE_IDENTIFIER",
+								optional => "NO",
+						   },
+						   {
+								type => "STRING",
+								name => "account_name",
+								help_string => "account name to send the qrcode OTP email to",
+								optional => "NO",
+								length => ["1", "USERNAME_LEN"],
+							},
+						 ],
+		return_result => [
+						{
+							result => "FAIL",
+							reason => "ERR_LOCALDB_MAIL_ADDR_NOT_FOUND",
+							info => "Cannot find the mail address for user: %s",
+						},
+		],
+	},
 	{
 		obj_type => "ITEM",
 		name => "export",
Index: /branches/rel_ag_9_4_5/ui/localcmd/ui_localdb.c
===================================================================
--- /branches/rel_ag_9_4_5/ui/localcmd/ui_localdb.c	(revision 20492)
+++ /branches/rel_ag_9_4_5/ui/localcmd/ui_localdb.c	(working copy)
@@ -10467,3 +10467,43 @@
 	return 0;
 
 }
+
+/*-------------[localdb_account]-----------------
+ * CLI implement: send a qrcode otp email to the user .
+ * CLI:
+ *     localdb account <user_name> <password>
+ */
+int
+localdb_sendqr(char *dbname, char *username)
+{
+	int ret;
+
+	ret = ldb_send_qrcode(dbname, username);
+
+	/* deal with error */
+	if (ret != LDB_SUCCESS) {
+	    switch(ret) {
+	        case LDB_ERR_INVALID_PARAM:
+	            ui_fail(ERR_LOCALDB_INVALID_PARAM, ERR_LOCALDB_INVALID_PARAM_INFO);
+	            break;
+	        case LDB_ERR_FAIL_CONN:
+	            ui_fail(ERR_LOCALDB_FAIL_CONN, ERR_LOCALDB_FAIL_CONN_INFO);
+	            break;
+	        case LDB_ERR_FAIL_EXEC:
+	            ui_fail(ERR_LOCALDB_FAIL_EXEC, ERR_LOCALDB_FAIL_EXEC_INFO);
+	            break;
+			case LDB_FAILURE:
+				ui_fail(ERR_LOCALDB_USER_NOT_FOUND, ERR_LOCALDB_USER_NOT_FOUND_INFO, username);
+				break;
+	        case LDB_ERR_EMPTY_RESULT:
+	            ui_fail(ERR_LOCALDB_MAIL_ADDR_NOT_FOUND, ERR_LOCALDB_MAIL_ADDR_NOT_FOUND_INFO, username);
+				break;
+			case LDB_ERR_EXIST:
+				ui_fail(ERR_LOCALDB_MAIL_ADDR_NOT_FOUND, ERR_LOCALDB_MAIL_ADDR_NOT_FOUND_INFO, username);
+	        default:
+	            break;
+	    }
+	    return -1;
+	}
+	return 0;
+}
Index: /branches/rel_ag_9_4_5/uproxy/sessmgrd/Makefile
===================================================================
--- /branches/rel_ag_9_4_5/uproxy/sessmgrd/Makefile	(revision 20492)
+++ /branches/rel_ag_9_4_5/uproxy/sessmgrd/Makefile	(working copy)
@@ -5,13 +5,13 @@
 LOCALDB_INCLUD=$(CA_ROOT)/localdb/pgsql/include
 LOCALDB_LIB=$(CA_ROOT)/localdb/pgsql/lib
 
-SDIRS = 
+SDIRS =
 
 CFLAGS += -D MPD_ONLY
 
 CINCLUDES = -I. -I$(TOP)/lib -I$(TOP)/utils -I$(TOP)/uproxy/utils/mpool/ -I$(TOP)/FreeBSD/src/sys -I$(TOP)/include \
                    -I$(TOP)/uproxy/utils/libdriver -I$(TOP)/lib/muxconnapi -I$(TOP)/localdb/include -I $(LOCALDB_INCLUD) \
-                   -I $(TOP)/fastlog/include -I$(TOP)/license/include/ -I$(TOP)/utils/sessmgr
+                   -I $(TOP)/fastlog/include -I$(TOP)/license/include/ -I$(TOP)/utils/sessmgr -I$(TOP)/localdb/jpeg
 
 LDFLAGS +=  -L$(TOP)/objdir -lsessmgr_api -lan_process -lan_ipc -lhash -llicense -L $(TOP)/utils/vsite/ -lvsite \
                   -L $(TOP)/kernelapi/lib -lkernelapi -L $(TOP)/utils/rpc/lib -lan_rpc \
@@ -22,8 +22,10 @@
                   -L $(TOP)/localdb/libldb -lldb \
                   -L ../utils/common -lcommon \
                   -L $(LOCALDB_LIB) -lpq -L$(TOP)/uproxy/utils/alwayson_logging/lib -lamp_ulog -L$(TOP)/fastlog/lib -lfastlog \
-                  -L $(TOP)/mpd/libmpdconfig -lmpdconfig -L $(TOP)/ha/halib/ -lhalib -lva -lip -lvip -llicense -lmemstat
-                  
+                  -L $(TOP)/mpd/libmpdconfig -lmpdconfig -L $(TOP)/ha/halib/ -lhalib -lva -lip -lvip -llicense -lmemstat \
+                  -L $(TOP)/localdb/libqrencode/.libs -lqrencode \
+                  -L $(TOP)/localdb/jpeg/.libs -ljpeg
+
 BIN = sessmgrd
 OBJS_MAIN =md5c.o sessmgrd.o sessmgrd_cli.o smanager_role.o
 
