示例#1
0
static void PrintPiecesThread(void* pv)
{
	CFrameWndEx* pFrame = (CFrameWndEx*)pv;
	CView* pView = pFrame->GetActiveView();
	CPrintDialog PD(FALSE, PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOPAGENUMS|PD_NOSELECTION, pFrame);

	if (theApp.DoPrintDialog(&PD) != IDOK)
		return; 

	if (PD.m_pd.hDC == NULL)
		return;

	Project* project = lcGetActiveProject();
	ObjArray<lcPiecesUsedEntry> PiecesUsed;

	project->GetPiecesUsed(PiecesUsed);
	PiecesUsed.Sort(PiecesUsedSortFunc, NULL);

	// gather file to print to if print-to-file selected
	CString strOutput;
	if (PD.m_pd.Flags & PD_PRINTTOFILE)
	{
		CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
		CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
		CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
		CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
		CFileDialog dlg(FALSE, strDef, strPrintDef,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
		dlg.m_ofn.lpstrTitle = strCaption;
		if (dlg.DoModal() != IDOK)
			return;
		strOutput = dlg.GetPathName();
	}

	CString DocName;
	char* Ext = strrchr(project->m_strTitle, '.');
	DocName.Format("LeoCAD - %.*s BOM", Ext ? Ext - project->m_strTitle : strlen(project->m_strTitle), project->m_strTitle);
	DOCINFO docInfo;
	memset(&docInfo, 0, sizeof(DOCINFO));
	docInfo.cbSize = sizeof(DOCINFO);
	docInfo.lpszDocName = DocName;
	CString strPortName;

	int nFormatID;
	if (strOutput.IsEmpty())
	{
		docInfo.lpszOutput = NULL;
		strPortName = PD.GetPortName();
		nFormatID = AFX_IDS_PRINTONPORT;
	}
	else
	{
		docInfo.lpszOutput = strOutput;
		AfxGetFileTitle(strOutput, strPortName.GetBuffer(_MAX_PATH), _MAX_PATH);
		nFormatID = AFX_IDS_PRINTTOFILE;
	}

	SetAbortProc(PD.m_pd.hDC, _AfxAbortProc);
	pFrame->EnableWindow(FALSE);
	CPrintingDialog dlgPrintStatus(NULL);

	CString strTemp;
	dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, DocName);
	dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME, PD.GetDeviceName());
	AfxFormatString1(strTemp, nFormatID, strPortName);
	dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp);
	dlgPrintStatus.ShowWindow(SW_SHOW);
	dlgPrintStatus.UpdateWindow();

	if (StartDoc(PD.m_pd.hDC, &docInfo) == SP_ERROR)
	{
		pFrame->EnableWindow(TRUE);
		dlgPrintStatus.DestroyWindow();
		AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
		return;
	}

	int ResX = GetDeviceCaps(PD.m_pd.hDC, LOGPIXELSX);
	int ResY = GetDeviceCaps(PD.m_pd.hDC, LOGPIXELSY);

	CRect RectDraw(0, 0, GetDeviceCaps(PD.m_pd.hDC, HORZRES), GetDeviceCaps(PD.m_pd.hDC, VERTRES));
	DPtoLP(PD.m_pd.hDC, (LPPOINT)(RECT*)&RectDraw, 2);
	RectDraw.DeflateRect((int)(ResX*(float)theApp.GetProfileInt("Default","Margin Left", 50)/100.0f),
	                     (int)(ResY*(float)theApp.GetProfileInt("Default","Margin Top", 50)/100.0f),
	                     (int)(ResX*(float)theApp.GetProfileInt("Default","Margin Right", 50)/100.0f),
	                     (int)(ResY*(float)theApp.GetProfileInt("Default","Margin Bottom", 50)/100.0f));

	CRect HeaderRect = RectDraw;
 	HeaderRect.top -= (int)(ResY*theApp.GetProfileInt("Default", "Margin Top", 50) / 200.0f);
	HeaderRect.bottom += (int)(ResY*theApp.GetProfileInt("Default", "Margin Bottom", 50) / 200.0f);

	int RowsPerPage = AfxGetApp()->GetProfileInt("Default", "Catalog Rows", 10);
	int ColsPerPage = AfxGetApp()->GetProfileInt("Default", "Catalog Columns", 3);
	int PicHeight = RectDraw.Height() / RowsPerPage;
	int PicWidth = RectDraw.Width() / ColsPerPage;
	int TotalRows = (PiecesUsed.GetSize() + ColsPerPage - 1) / ColsPerPage;
	int TotalPages = (TotalRows + RowsPerPage - 1) / RowsPerPage;
	int RowHeight = RectDraw.Height() / RowsPerPage;
	int ColWidth = RectDraw.Width() / ColsPerPage;

	PD.m_pd.nMinPage = 1;
	PD.m_pd.nMaxPage = TotalPages + 1;

	UINT EndPage = PD.m_pd.nToPage;
	UINT StartPage = PD.m_pd.nFromPage;
	if (PD.PrintAll())
	{
		EndPage = PD.m_pd.nMaxPage;
		StartPage = PD.m_pd.nMinPage;
	}

	lcClamp(EndPage, PD.m_pd.nMinPage, PD.m_pd.nMaxPage);
	lcClamp(StartPage, PD.m_pd.nMinPage, PD.m_pd.nMaxPage);
	int StepPage = (EndPage >= StartPage) ? 1 : -1;

	VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM));

	// begin page printing loop
	BOOL bError = FALSE;

	// Creating Compatible Memory Device Context
	CDC *pMemDC = new CDC;
	if (!pMemDC->CreateCompatibleDC(pView->GetDC()))
		return;

	BITMAPINFO bi;
	ZeroMemory(&bi, sizeof(BITMAPINFO));
	bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bi.bmiHeader.biWidth = PicWidth;
	bi.bmiHeader.biHeight = PicHeight;
	bi.bmiHeader.biPlanes = 1;
	bi.bmiHeader.biBitCount = 24;
	bi.bmiHeader.biCompression = BI_RGB;
	bi.bmiHeader.biSizeImage = PicWidth * PicHeight * 3;
	bi.bmiHeader.biXPelsPerMeter = 2925;
	bi.bmiHeader.biYPelsPerMeter = 2925;
	bi.bmiHeader.biClrUsed = 0;
	bi.bmiHeader.biClrImportant = 0;
	
	LPBITMAPINFOHEADER lpbi[1];

	HBITMAP hBm, hBmOld;
    hBm = CreateDIBSection(pView->GetDC()->GetSafeHdc(), &bi, DIB_RGB_COLORS, (void **)&lpbi, NULL, (DWORD)0);
	if (!hBm)
		return;
	hBmOld = (HBITMAP)::SelectObject(pMemDC->GetSafeHdc(), hBm);

	PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI,
			PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 };
	int pixelformat = ChoosePixelFormat(pMemDC->m_hDC, &pfd);
	DescribePixelFormat(pMemDC->m_hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
	SetPixelFormat(pMemDC->m_hDC, pixelformat, &pfd);
	HGLRC hmemrc = wglCreateContext(pMemDC->GetSafeHdc());
	wglMakeCurrent(pMemDC->GetSafeHdc(), hmemrc);

	GL_DisableVertexBufferObject();
	float Aspect = (float)PicWidth/(float)PicHeight;

	glViewport(0, 0, PicWidth, PicHeight);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(0.5f, 0.1f);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glClearColor(1, 1, 1, 1); 

	LOGFONT lf;
	memset(&lf, 0, sizeof(LOGFONT));
	lf.lfHeight = -MulDiv(12, ResY, 72);
	lf.lfWeight = FW_REGULAR;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfQuality = PROOF_QUALITY;
	strcpy (lf.lfFaceName , "Arial");

	HFONT HeaderFont = CreateFontIndirect(&lf);
	HFONT OldFont = (HFONT)SelectObject(PD.m_pd.hDC, HeaderFont);
	SetBkMode(PD.m_pd.hDC, TRANSPARENT);
	SetTextColor(PD.m_pd.hDC, 0x000000);
	SetTextAlign(PD.m_pd.hDC, TA_CENTER|TA_NOUPDATECP);

	DWORD PrintOptions = AfxGetApp()->GetProfileInt("Settings", "Print", PRINT_NUMBERS | PRINT_BORDER/*|PRINT_NAMES*/);
	bool DrawNames = 1;//(PrintOptions & PRINT_NAMES) != 0;
	bool Horizontal = 1;//(PrintOptions & PRINT_HORIZONTAL) != 0;

	pMemDC->SetTextColor(0x000000);
	pMemDC->SetBkMode(TRANSPARENT);
//	lf.lfHeight = -MulDiv(40, GetDeviceCaps(pMemDC->m_hDC, LOGPIXELSY), 72);
//	lf.lfWeight = FW_BOLD;
	HFONT CatalogFont = CreateFontIndirect(&lf);
	lf.lfHeight = -MulDiv(80, GetDeviceCaps(pMemDC->m_hDC, LOGPIXELSY), 72);
	HFONT CountFont = CreateFontIndirect(&lf);
	HFONT OldMemFont = (HFONT)SelectObject(pMemDC->m_hDC, CatalogFont);
	HPEN hpOld = (HPEN)SelectObject(pMemDC->m_hDC, GetStockObject(BLACK_PEN));

	for (UINT CurPage = StartPage; CurPage != EndPage; CurPage += StepPage)
	{
		TCHAR szBuf[80];
		wsprintf(szBuf, strTemp, CurPage);
		dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf);
		if (::StartPage(PD.m_pd.hDC) < 0)
		{
			bError = TRUE;
			break;
		}

		// Draw header and footer.
		SelectObject(PD.m_pd.hDC, HeaderFont);

		CString Header;
		UINT Align;

		FormatHeader(Header, Align, AfxGetApp()->GetProfileString("Default", "Catalog Header", ""), project->m_strTitle, project->m_strAuthor, project->m_strDescription, CurPage, TotalPages);
		Align |= DT_TOP|DT_SINGLELINE;

		DrawText(PD.m_pd.hDC, (LPCTSTR)Header, Header.GetLength(), HeaderRect, Align);

		FormatHeader(Header, Align, AfxGetApp()->GetProfileString("Default", "Catalog Footer", "Page &P"), project->m_strTitle, project->m_strAuthor, project->m_strDescription, CurPage, TotalPages);
		Align |= DT_BOTTOM|DT_SINGLELINE;

		DrawText(PD.m_pd.hDC, (LPCTSTR)Header, Header.GetLength(), HeaderRect, Align);

		int StartPiece = (CurPage - 1) * RowsPerPage * ColsPerPage;
		int EndPiece = lcMin(StartPiece + RowsPerPage * ColsPerPage, PiecesUsed.GetSize());

		for (int CurPiece = StartPiece; CurPiece < EndPiece; CurPiece++)
		{
			FillRect(pMemDC->m_hDC, CRect(0, PicHeight, PicWidth, 0), (HBRUSH)GetStockObject(WHITE_BRUSH));
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			PieceInfo* pInfo = PiecesUsed[CurPiece].Info;
			pInfo->ZoomExtents(30.0f, Aspect);

			pInfo->RenderPiece(PiecesUsed[CurPiece].ColorIndex);
			glFinish();

			// Draw description text at the bottom.
			CRect TextRect(0, 0, PicWidth, PicHeight);
	
			if (DrawNames)
			{
				SelectObject(pMemDC->m_hDC, CatalogFont);
				pMemDC->DrawText(pInfo->m_strDescription, strlen(pInfo->m_strDescription), TextRect, DT_CALCRECT | DT_WORDBREAK);

				TextRect.OffsetRect(0, PicHeight - TextRect.Height() - 5);
				pMemDC->DrawText(pInfo->m_strDescription, strlen(pInfo->m_strDescription), TextRect, DT_WORDBREAK);
			}

			// Draw count.
			SelectObject(pMemDC->m_hDC, CountFont);
			TextRect = CRect(0, 0, PicWidth, TextRect.top);
			TextRect.DeflateRect(5, 5);

			char CountStr[16];
			sprintf(CountStr, "%dx", PiecesUsed[CurPiece].Count);
			pMemDC->DrawText(CountStr, strlen(CountStr), TextRect, DT_BOTTOM | DT_LEFT | DT_SINGLELINE);

			LPBITMAPINFOHEADER lpbi[1];
			lpbi[0] = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hBm, 24));
			BITMAPINFO bi;
			ZeroMemory(&bi, sizeof(BITMAPINFO));
			memcpy (&bi.bmiHeader, lpbi[0], sizeof(BITMAPINFOHEADER));
			SetStretchBltMode(PD.m_pd.hDC, COLORONCOLOR);

			int CurRow, CurCol;

			if (Horizontal)
			{
				CurRow = (CurPiece - StartPiece) / ColsPerPage;
				CurCol = (CurPiece - StartPiece) % ColsPerPage;
			}
			else
			{
				CurRow = (CurPiece - StartPiece) % RowsPerPage;
				CurCol = (CurPiece - StartPiece) / RowsPerPage;
			}
			
			int Left = RectDraw.left + ColWidth * CurCol + (ColWidth - PicWidth) / 2;
			int Top = RectDraw.top + RowHeight * CurRow + (RowHeight - PicHeight) / 2;

			StretchDIBits(PD.m_pd.hDC, Left, Top, PicWidth, PicHeight, 0, 0, PicWidth, PicHeight, 
			              (LPBYTE)lpbi[0] + lpbi[0]->biSize + lpbi[0]->biClrUsed * sizeof(RGBQUAD), &bi, DIB_RGB_COLORS, SRCCOPY);
			if (lpbi[0])
				GlobalFreePtr(lpbi[0]);
		}

		if (::EndPage(PD.m_pd.hDC) < 0 || !_AfxAbortProc(PD.m_pd.hDC, 0))
		{
			bError = TRUE;
			break;
		}
	}

	SelectObject(pMemDC->m_hDC, hpOld);
	SelectObject(PD.m_pd.hDC, OldFont);
	DeleteObject(HeaderFont);
	SelectObject(pMemDC->m_hDC, OldMemFont);
	DeleteObject(CatalogFont);
	DeleteObject(CountFont);

	GL_EnableVertexBufferObject();
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(hmemrc);
	SelectObject(pMemDC->GetSafeHdc(), hBmOld);
	DeleteObject(hBm);
	delete pMemDC;

	if (!bError)
		EndDoc(PD.m_pd.hDC);
	else
		AbortDoc(PD.m_pd.hDC);

	pFrame->EnableWindow();
	dlgPrintStatus.DestroyWindow();

	if (PD.m_pd.hDC != NULL)
    {
		::DeleteDC(PD.m_pd.hDC);
		PD.m_pd.hDC = NULL;
    }
}
示例#2
0
////////////////////////////////////////////////////////////////////////////////
//        NAME: Send
// DESCRIPTION: Sending the mail. .
//   ARGUMENTS: none
// USES GLOBAL: m_sSMTPSrvName, m_iSMTPSrvPort, SendBuf, RecvBuf, m_sLogin,
//              m_sPassword, m_sMailFrom, Recipients, CCRecipients,
//              BCCRecipients, m_sMsgBody, Attachments,
// MODIFIES GL: SendBuf
//     RETURNS: void
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
//							JP 2010-07-08
////////////////////////////////////////////////////////////////////////////////
void CSmtp::Send()
{
	unsigned int i,rcpt_count,res,FileId;
	char *FileBuf = NULL, *FileName = NULL;
	FILE* hFile = NULL;
	unsigned long int FileSize,TotalSize,MsgPart;
	bool bAccepted;

	// ***** CONNECTING TO SMTP SERVER *****

	// connecting to remote host:
	if( (hSocket = ConnectRemoteServer(m_sSMTPSrvName.c_str(), m_iSMTPSrvPort)) == INVALID_SOCKET )
		throw ECSmtp(ECSmtp::WSA_INVALID_SOCKET, NULL);

	bAccepted = false;
	do
	{
		ReceiveData();
		switch(SmtpXYZdigits())
		{
			case 220:
				bAccepted = true;
				break;
			default:
				throw ECSmtp(ECSmtp::SERVER_NOT_READY, RecvBuf);
		}
	}while(!bAccepted);

	// EHLO <SP> <domain> <CRLF>
	sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_sLocalHostName.c_str() : "domain");
	SendData();
	bAccepted = false;
	do
	{
		ReceiveData();
		switch(SmtpXYZdigits())
		{
			case 250:
				bAccepted = true;
				break;
			default:
				throw ECSmtp(ECSmtp::COMMAND_EHLO, RecvBuf);
		}
	}while(!bAccepted);

    if(!m_sLogin.empty())
    {

        // AUTH <SP> LOGIN <CRLF>
        strcpy(SendBuf,"AUTH LOGIN\r\n");
        SendData();
        bAccepted = false;
        do
        {
            ReceiveData();
            switch(SmtpXYZdigits())
            {
                case 250:
                    break;
                case 334:
                    bAccepted = true;
                    break;
                default:
                    throw ECSmtp(ECSmtp::COMMAND_AUTH_LOGIN, RecvBuf);
            }
        }while(!bAccepted);

        // send login:
        if(!m_sLogin.size())
            throw ECSmtp(ECSmtp::UNDEF_LOGIN, RecvBuf);
        std::string encoded_login = base64_encode(reinterpret_cast<const unsigned char*>(m_sLogin.c_str()),m_sLogin.size());
        sprintf(SendBuf,"%s\r\n",encoded_login.c_str());
        SendData();
        bAccepted = false;
        do
        {
            ReceiveData();
            switch(SmtpXYZdigits())
            {
                case 334:
                    bAccepted = true;
                    break;
                default:
                    throw ECSmtp(ECSmtp::UNDEF_XYZ_RESPONSE, RecvBuf);
            }
        }while(!bAccepted);

        // send password:
        if(!m_sPassword.size())
            throw ECSmtp(ECSmtp::UNDEF_PASSWORD, RecvBuf);
        std::string encoded_password = base64_encode(reinterpret_cast<const unsigned char*>(m_sPassword.c_str()),m_sPassword.size());
        sprintf(SendBuf,"%s\r\n",encoded_password.c_str());
        SendData();
        bAccepted = false;
        do
        {
            ReceiveData();
            switch(SmtpXYZdigits())
            {
                case 235:
                    bAccepted = true;
                    break;
                case 334:
                    break;
                case 535:
                    throw ECSmtp(ECSmtp::BAD_LOGIN_PASS, RecvBuf);
                default:
                    throw ECSmtp(ECSmtp::UNDEF_XYZ_RESPONSE, RecvBuf);
            }
        }while(!bAccepted);
    }

	// ***** SENDING E-MAIL *****

	// MAIL <SP> FROM:<reverse-path> <CRLF>
	if(!m_sMailFrom.size())
		throw ECSmtp(ECSmtp::UNDEF_MAIL_FROM, RecvBuf);
	sprintf(SendBuf,"MAIL FROM:<%s>\r\n",m_sMailFrom.c_str());
	SendData();
	bAccepted = false;
	do
	{
		ReceiveData();
		switch(SmtpXYZdigits())
		{
			case 250:
				bAccepted = true;
				break;
			default:
				throw ECSmtp(ECSmtp::COMMAND_MAIL_FROM, RecvBuf);
		}
	}while(!bAccepted);

	// RCPT <SP> TO:<forward-path> <CRLF>
	if(!(rcpt_count = Recipients.size()))
		throw ECSmtp(ECSmtp::UNDEF_RECIPIENTS, NULL);
	for(i=0;i<Recipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(Recipients.at(i).Mail).c_str());
		SendData();
		bAccepted = false;
		do
		{
			ReceiveData();
			switch(SmtpXYZdigits())
			{
				case 250:
					bAccepted = true;
					break;
				default:
					rcpt_count--;
			}
		}while(!bAccepted);
	}
	if(rcpt_count <= 0)
		throw ECSmtp(ECSmtp::COMMAND_RCPT_TO, RecvBuf);

	for(i=0;i<CCRecipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(CCRecipients.at(i).Mail).c_str());
		SendData();
		bAccepted = false;
		do
		{
			ReceiveData();
			switch(SmtpXYZdigits())
			{
				case 250:
					bAccepted = true;
					break;
				default:
					; // not necessary to throw
			}
		}while(!bAccepted);
	}

	for(i=0;i<BCCRecipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());
		SendData();
		bAccepted = false;
		do
		{
			ReceiveData();
			switch(SmtpXYZdigits())
			{
				case 250:
					bAccepted = true;
					break;
				default:
					; // not necessary to throw
			}
		}while(!bAccepted);
	}

	// DATA <CRLF>
	strcpy(SendBuf,"DATA\r\n");
	SendData();
	bAccepted = false;
	do
	{
		ReceiveData();
		switch(SmtpXYZdigits())
		{
			case 354:
				bAccepted = true;
				break;
			case 250:
				break;
			default:
				throw ECSmtp(ECSmtp::COMMAND_DATA, RecvBuf);
		}
	}while(!bAccepted);

	// send header(s)
	FormatHeader(SendBuf);
	SendData();

	// send text message
	if(GetMsgLines())
	{
		for(i=0;i<GetMsgLines();i++)
		{
			sprintf(SendBuf,"%s\r\n",GetMsgLineText(i));
			SendData();
		}
	}
	else
	{
		sprintf(SendBuf,"%s\r\n"," ");
		SendData();
	}

	// next goes attachments (if they are)
	if((FileBuf = new char[55]) == NULL)
		throw ECSmtp(ECSmtp::LACK_OF_MEMORY, RecvBuf);

	if((FileName = new char[255]) == NULL)
		throw ECSmtp(ECSmtp::LACK_OF_MEMORY, RecvBuf);

	TotalSize = 0;
	for(FileId=0;FileId<Attachments.size();FileId++)
	{
		strcpy(FileName,Attachments[FileId].c_str());

		sprintf(SendBuf,"--%s\r\n",BOUNDARY_TEXT);
		strcat(SendBuf,"Content-Type: application/x-msdownload; name=\"");
		strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
		strcat(SendBuf,"\"\r\n");
		strcat(SendBuf,"Content-Transfer-Encoding: base64\r\n");
		strcat(SendBuf,"Content-Disposition: attachment; filename=\"");
		strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
		strcat(SendBuf,"\"\r\n");
		strcat(SendBuf,"\r\n");

		SendData();

		// opening the file:
		hFile = fopen(FileName,"rb");
		if(hFile == NULL)
			throw ECSmtp(ECSmtp::FILE_NOT_EXIST, RecvBuf);

		// checking file size:
		FileSize = 0;
		while(!feof(hFile))
			FileSize += fread(FileBuf,sizeof(char),54,hFile);
		TotalSize += FileSize;

		// sending the file:
		if(TotalSize/1024 > MSG_SIZE_IN_MB*1024)
			throw ECSmtp(ECSmtp::MSG_TOO_BIG, RecvBuf);
		else
		{
			fseek (hFile,0,SEEK_SET);

			MsgPart = 0;
			for(i=0;i<FileSize/54+1;i++)
			{
				res = fread(FileBuf,sizeof(char),54,hFile);
				MsgPart ? strcat(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str())
					      : strcpy(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str());
				strcat(SendBuf,"\r\n");
				MsgPart += res + 2;
				if(MsgPart >= BUFFER_SIZE/2)
				{ // sending part of the message
					MsgPart = 0;
					SendData(); // FileBuf, FileName, fclose(hFile);
				}
			}
			if(MsgPart)
			{
				SendData(); // FileBuf, FileName, fclose(hFile);
			}
		}
		fclose(hFile);
	}
	delete[] FileBuf;
	delete[] FileName;

	// sending last message block (if there is one or more attachments)
	if(Attachments.size())
	{
		sprintf(SendBuf,"\r\n--%s--\r\n",BOUNDARY_TEXT);
		SendData();
	}

	// <CRLF> . <CRLF>
	strcpy(SendBuf,"\r\n.\r\n");
	SendData();
	bAccepted = false;
	do
	{
		ReceiveData();
		switch(SmtpXYZdigits())
		{
			case 250:
				bAccepted = true;
				break;
			default:
				throw ECSmtp(ECSmtp::MSG_BODY_ERROR, RecvBuf);
		}
	}while(!bAccepted);

	// ***** CLOSING CONNECTION *****

	// QUIT <CRLF>
	strcpy(SendBuf,"QUIT\r\n");
	SendData();
	bAccepted = false;
	do
	{
		ReceiveData();
		switch(SmtpXYZdigits())
		{
			case 221:
				bAccepted = true;
				break;
			default:
				throw ECSmtp(ECSmtp::COMMAND_QUIT, RecvBuf);
		}
	}while(!bAccepted);

#ifdef LINUX
	close(hSocket);
#else
	closesocket(hSocket);
#endif
	hSocket = 0;
}
示例#3
0
bool CSmtp::Send()
{
	unsigned int i,rcpt_count,res,FileId;
	char *FileBuf = NULL, *FileName = NULL;
	FILE* hFile = NULL;
	unsigned long int FileSize,TotalSize,MsgPart;

	// ***** CONNECTING TO SMTP SERVER *****

	assert(m_pcSMTPSrvName);

	// connecting to remote host:
	if( (hSocket = ConnectRemoteServer(m_pcSMTPSrvName, m_iSMTPSrvPort)) == INVALID_SOCKET ) 
	{
		m_oError = CSMTP_WSA_INVALID_SOCKET;
		return false;
	}
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 220:
			break;
		default:
			m_oError = CSMTP_SERVER_NOT_READY;
			return false;
	}

	// EHLO <SP> <domain> <CRLF>
	sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_pcLocalHostName : "domain");
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 250:
			break;
		default:
			m_oError = CSMTP_COMMAND_EHLO;
			return false;
	}

	// AUTH <SP> LOGIN <CRLF>
	strcpy(SendBuf,"AUTH LOGIN\r\n");
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 334:
			break;
		default:
			m_oError = CSMTP_COMMAND_AUTH_LOGIN;
			return false;
	}

	// send login:
	if(!m_pcLogin)
	{
		m_oError = CSMTP_UNDEF_LOGIN;
		return false;
	}
	std::string encoded_login = base64_encode(reinterpret_cast<const unsigned char*>(m_pcLogin),strlen(m_pcLogin));
	sprintf(SendBuf,"%s\r\n",encoded_login.c_str());
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 334:
			break;
		default:
			m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
			return false;
	}
	
	// send password:
	if(!m_pcPassword)
	{
		m_oError = CSMTP_UNDEF_PASSWORD;
		return false;
	}
	std::string encoded_password = base64_encode(reinterpret_cast<const unsigned char*>(m_pcPassword),strlen(m_pcPassword));
	sprintf(SendBuf,"%s\r\n",encoded_password.c_str());
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 235:
			break;
		case 535:
			m_oError = CSMTP_BAD_LOGIN_PASS;
			return false;
		default:
			m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
			return false;
	}

	// ***** SENDING E-MAIL *****
	
	// MAIL <SP> FROM:<reverse-path> <CRLF>
	if(m_pcMailFrom == NULL)
	{
		m_oError = CSMTP_UNDEF_MAILFROM;
		return false;
	}
	sprintf(SendBuf,"MAIL FROM:<%s>\r\n",m_pcMailFrom);
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 250:
			break;
		default:
			m_oError = CSMTP_COMMAND_MAIL_FROM;
			return false;
	}

	// RCPT <SP> TO:<forward-path> <CRLF>
	rcpt_count = Recipients.size();
	for(i=0;i<Recipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(Recipients.at(i).Mail).c_str());
		if(!SendData())
			return false;
		Sleep(DELAY_IN_MS);
		if(!ReceiveData())
			return false;

		switch(SmtpXYZdigits())
		{
			case 250:
				break;
			default:
				m_oError = CSMTP_COMMAND_RCPT_TO;
				rcpt_count--;
		}
	}
	if(!rcpt_count)
		return false;
	for(i=0;i<CCRecipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(CCRecipients.at(i).Mail).c_str());
		if(!SendData())
			return false;
		Sleep(DELAY_IN_MS);
		if(!ReceiveData())
			return false;
	}
	for(i=0;i<BCCRecipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());
		if(!SendData())
			return false;
		Sleep(DELAY_IN_MS);
		if(!ReceiveData())
			return false;
	}
	
	// DATA <CRLF>
	strcpy(SendBuf,"DATA\r\n");
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;
	
	switch(SmtpXYZdigits())
	{
		case 354:
			break;
		default:
			m_oError = CSMTP_COMMAND_DATA;
			return false;
	}
	
	// send header(s)
	if(!FormatHeader(SendBuf))
	{
		m_oError = CSMTP_UNDEF_MSG_HEADER;
		return false;
	}
	if(!SendData())
		return false;

	// send text message
	sprintf(SendBuf,"%s\r\n",m_pcMsgBody); // NOTICE: each line ends with <CRLF>
	if(!SendData())
		return false;

	// next goes attachments (if they are)
	if((FileBuf = new char[55]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return false;
	}
	if((FileName = new char[255]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return false;
	}
	TotalSize = 0;
	for(FileId=0;FileId<Attachments.size();FileId++)
	{
		strcpy(FileName,Attachments[FileId].c_str());

		sprintf(SendBuf,"--%s\r\n",BOUNDARY_TEXT);
		strcat(SendBuf,"Content-Type: application/x-msdownload; name=\"");
		strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
		strcat(SendBuf,"\"\r\n");
		strcat(SendBuf,"Content-Transfer-Encoding: base64\r\n");
		strcat(SendBuf,"Content-Disposition: attachment; filename=\"");
		strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
		strcat(SendBuf,"\"\r\n");
		strcat(SendBuf,"\r\n");

		if(!SendData())
			return false;

		// opening the file:
		hFile = fopen(FileName,"rb");
		if(hFile == NULL)
		{
			m_oError = CSMTP_FILE_NOT_EXIST;
			break;
		}
		
		// checking file size:
		FileSize = 0;
		while(!feof(hFile))
			FileSize += fread(FileBuf,sizeof(char),54,hFile);
		TotalSize += FileSize;

		// sending the file:
		if(TotalSize/1024 > MSG_SIZE_IN_MB*1024)
			m_oError = CSMTP_MSG_TOO_BIG;
		else
		{
			fseek (hFile,0,SEEK_SET);

			MsgPart = 0;
			for(i=0;i<FileSize/54+1;i++)
			{
				res = fread(FileBuf,sizeof(char),54,hFile);
				MsgPart ? strcat(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str())
					      : strcpy(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str());
				strcat(SendBuf,"\r\n");
				MsgPart += res + 2;
				if(MsgPart >= BUFFER_SIZE/2)
				{ // sending part of the message
					MsgPart = 0;
					if(!SendData())
					{
						delete[] FileBuf;
						delete[] FileName;
						fclose(hFile);
						return false;
					}
				}
			}
			if(MsgPart)
			{
				if(!SendData())
				{
					delete[] FileBuf;
					delete[] FileName;
					fclose(hFile);
					return false;
				}
			}
		}
		fclose(hFile);
	}
	delete[] FileBuf;
	delete[] FileName;
	
	// sending last message block (if there is one or more attachments)
	if(Attachments.size())
	{
		sprintf(SendBuf,"\r\n--%s--\r\n",BOUNDARY_TEXT);
		if(!SendData())
			return false;
	}
	
	// <CRLF> . <CRLF>
	strcpy(SendBuf,"\r\n.\r\n");
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 250:
			break;
		default:
			m_oError = CSMTP_MSG_BODY_ERROR;
			return false;
	}

	// ***** CLOSING CONNECTION *****
	
	// QUIT <CRLF>
	strcpy(SendBuf,"QUIT\r\n");
	if(!SendData())
		return false;
	Sleep(DELAY_IN_MS);
	if(!ReceiveData())
		return false;

	switch(SmtpXYZdigits())
	{
		case 221:
			break;
		default:
			m_oError = CSMTP_COMMAND_QUIT;
			hSocket = NULL;
			return false;
	}

	closesocket(hSocket);
	hSocket = NULL;
	return true;
}