inline wchar_t *wxStrncpy(wchar_t *dest, const char *src, size_t n)
{ return wxCRT_StrncpyW(dest, wxConvLibc.cMB2WC(src), n); }
+// this is a new function so we don't care about backwards compatibility and
+// so don't need to support wchar_t/char overloads
+inline size_t wxStrlcpy(char *dest, const char *src, size_t n)
+{
+ const size_t len = wxCRT_StrlenA(src);
+
+ if ( n )
+ {
+ if ( n-- > len )
+ n = len;
+ wxCRT_StrncpyA(dest, src, n);
+ dest[n] = '\0';
+ }
+
+ return len;
+}
+inline size_t wxStrlcpy(wchar_t *dest, const wchar_t *src, size_t n)
+{
+ const size_t len = wxCRT_StrlenW(src);
+ if ( n )
+ {
+ if ( n-- > len )
+ n = len;
+ wxCRT_StrncpyW(dest, src, n);
+ dest[n] = L'\0';
+ }
+
+ return len;
+}
+
inline char *wxStrcat(char *dest, const char *src)
{ return wxCRT_StrcatA(dest, src); }
inline wchar_t *wxStrcat(wchar_t *dest, const wchar_t *src)
const wxString& delims = wxDEFAULT_DELIMITERS,
wxStringTokenizerMode mode = wxTOKEN_DEFAULT);
+/**
+ Safe and more convenient replacement for strncpy().
+
+ This function copies the source string @a src to the destination buffer @a
+ dst of size @a n without overflowing the buffer and ensuring that it is
+ always @NUL-terminated.
+
+ Example of use:
+ @code
+ char buf[256];
+ if ( wxStrlcpy(buf, GetSomeString(), WXSIZEOF(buf)) > WXSIZEOF(buf) )
+ ... handle truncation ...
+ @endcode
+ Notice that using wxStrncpy() in similar way is wrong, the above is broadly
+ equivalent to
+ @code
+ char buf[256];
+ buf[WXSIZEOF(buf) - 1] = '\0';
+ wxStrncpy(buf, GetSomeString(), WXSIZEOF(buf) - 1);
+ if ( buf[WXSIZEOF(buf) - 1] != '\0' )
+ {
+ ... truncation occurred ...
+ // need to NUL-terminate string manually
+ buf[WXSIZEOF(buf) - 1] = '\0';
+ }
+ @endcode
+ which should explain the advantage of using wxStrlcpy().
+
+ Notice that this function is similar to the OpenBSD strlcpy() function.
+
+ The template parameter @a T can be either @c char or @c wchar_t.
+
+ @param dst
+ Destination buffer of size (greater or) equal to @a n.
+ @param src
+ @NUL-terminated source string.
+ @param n
+ The size of the destination buffer.
+ @return
+ The length of @a src, if the returned value is greater or equal to @a n
+ then there was not enough space in the destination buffer and the
+ string was truncated.
+
+ @since{2.9.0}
+
+ @header{wx/wxcrt.h}
+ */
+template <typename T>
+size_t wxStrlcpy(T *dst, const T *src, size_t n);
+
/**
This function replaces the dangerous standard function @e sprintf() and is
like @e snprintf() available on some platforms. The only difference with
static char buf[128];
wxString fmt(dt->Format("%Y-%m-%d (%a) %H:%M:%S"));
- wxStrncpy(buf, fmt + " (" + dt->GetValue().ToString() + " ticks)",
+ wxStrlcpy(buf, fmt + " (" + dt->GetValue().ToString() + " ticks)",
WXSIZEOF(buf));
return buf;
#if !defined(__SMARTPHONE__) /* of WinCE */
if( lpMsgBuf != 0 )
{
- wxStrncpy(s_szBuf, (const wxChar *)lpMsgBuf, WXSIZEOF(s_szBuf) - 1);
- s_szBuf[WXSIZEOF(s_szBuf) - 1] = wxS('\0');
+ wxStrlcpy(s_szBuf, (const wxChar *)lpMsgBuf, WXSIZEOF(s_szBuf));
LocalFree(lpMsgBuf);
if ( !email )
return false;
- wxStrncpy(address, email, maxSize - 1);
- address[maxSize - 1] = wxT('\0');
+ wxStrlcpy(address, email, maxSize);
return true;
}
bool wxGetClipboardFormatName(const wxDataFormat& dataFormat, char *formatName,
int maxCount)
{
- wxStrncpy( formatName, dataFormat.GetId().c_str(), maxCount );
+ wxStrlcpy( formatName, dataFormat.GetId().c_str(), maxCount );
return true;
}
if (!user)
user = _T("user");
- wxStrncpy(buf, user, n);
+ wxStrlcpy(buf, user, n);
return true;
}
if (!host)
host = _T("host");
- wxStrncpy(buf, host, n);
+ wxStrlcpy(buf, host, n);
return true;
}
WNDCLASS *lpWndClass)
{
const size_t length = uniqueClassName.length() + 1; // for trailing NUL
- wxChar *newChars = new wxChar[length];
- wxStrncpy(newChars, uniqueClassName, length);
+ wxChar * const newChars = new wxChar[length];
+ wxStrlcpy(newChars, uniqueClassName, length);
*className = newChars;
lpWndClass->lpszClassName = *className;
/* static */
void wxCrashReport::SetFileName(const wxString& filename)
{
- wxStrncpy(gs_reportFilename, filename.c_str(), WXSIZEOF(gs_reportFilename) - 1);
- gs_reportFilename[WXSIZEOF(gs_reportFilename) - 1] = _T('\0');
+ wxStrlcpy(gs_reportFilename, filename.wx_str(), WXSIZEOF(gs_reportFilename));
}
/* static */
RASDIALPARAMS rasDialParams;
rasDialParams.dwSize = sizeof(rasDialParams);
- wxStrncpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName);
+ wxStrlcpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName);
// do we have the username and password?
if ( !username || !password )
}
else
{
- wxStrncpy(rasDialParams.szUserName, username, UNLEN);
- wxStrncpy(rasDialParams.szPassword, password, PWLEN);
+ wxStrlcpy(rasDialParams.szUserName, username, UNLEN);
+ wxStrlcpy(rasDialParams.szPassword, password, PWLEN);
}
// default values for other fields
//=== Setting defaultFileName >>=========================================
- wxStrncpy(fileNameBuffer, m_fileName, wxMAXPATH-1);
- fileNameBuffer[ wxMAXPATH-1 ] = wxT('\0');
+ wxStrlcpy(fileNameBuffer, m_fileName, WXSIZEOF(fileNameBuffer));
of.lpstrFile = fileNameBuffer; // holds returned filename
of.nMaxFile = wxMAXPATH;
extension = extension + wxStrlen( extension ) + 1;
m_fileName = AppendExtension(fileNameBuffer, extension);
- wxStrncpy(fileNameBuffer, m_fileName.c_str(), wxMin(m_fileName.length(), wxMAXPATH-1));
- fileNameBuffer[wxMin(m_fileName.length(), wxMAXPATH-1)] = wxT('\0');
+ wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
}
m_path = fileNameBuffer;
bool wxNativeFontInfo::SetFaceName(const wxString& facename)
{
- size_t len = WXSIZEOF(lf.lfFaceName);
- wxStrncpy(lf.lfFaceName, facename, len);
- lf.lfFaceName[len - 1] = '\0'; // truncate the face name
+ wxStrlcpy(lf.lfFaceName, facename, WXSIZEOF(lf.lfFaceName));
return true;
}
#else // __WIN32__
LOGFONT lf;
lf.lfCharSet = (BYTE)m_charset;
- wxStrncpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
+ wxStrlcpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
lf.lfPitchAndFamily = 0;
::EnumFontFamiliesEx(hDC, &lf, (wxFONTENUMPROC)wxFontEnumeratorProc,
(LPARAM)this, 0 /* reserved */) ;
wxZeroMemory(lf); // all default values
lf.lfCharSet = (BYTE)info.charset;
- wxStrncpy(lf.lfFaceName, info.facename, WXSIZEOF(lf.lfFaceName));
+ wxStrlcpy(lf.lfFaceName, info.facename, WXSIZEOF(lf.lfFaceName));
HFONT hfont = ::CreateFontIndirect(&lf);
if ( !hfont )
if ( lvi.mask & LVIF_TEXT )
{
wxString text = OnGetItemText(item, lvi.iSubItem);
- wxStrncpy(lvi.pszText, text, lvi.cchTextMax - 1);
- lvi.pszText[lvi.cchTextMax - 1] = _T('\0');
+ wxStrlcpy(lvi.pszText, text, lvi.cchTextMax);
}
// see comment at the end of wxListCtrl::GetColumn()
{
// NB: the cast is needed in the ANSI build, strangely enough
// dmDeviceName is BYTE[] and not char[] there
- wxStrncpy(reinterpret_cast<wxChar *>(devMode->dmDeviceName),
+ wxStrlcpy(reinterpret_cast<wxChar *>(devMode->dmDeviceName),
name.wx_str(),
- WXSIZEOF(devMode->dmDeviceName) - 1);
- devMode->dmDeviceName[WXSIZEOF(devMode->dmDeviceName) - 1] = wxT('\0');
+ WXSIZEOF(devMode->dmDeviceName));
}
//// Colour
notifyData.uFlags |= NIF_TIP;
if ( !tooltip.empty() )
{
- wxStrncpy(notifyData.szTip, tooltip.wx_str(), WXSIZEOF(notifyData.szTip));
+ wxStrlcpy(notifyData.szTip, tooltip.wx_str(), WXSIZEOF(notifyData.szTip));
}
bool ok = wxShellNotifyIcon(m_iconAdded ? NIM_MODIFY
notifyData = NotifyIconData(hwnd);
notifyData.uFlags |= NIF_INFO;
notifyData.uTimeout = msec;
- wxStrncpy(notifyData.szInfo, text.wx_str(), WXSIZEOF(notifyData.szInfo));
- wxStrncpy(notifyData.szInfoTitle, title.wx_str(),
+ wxStrlcpy(notifyData.szInfo, text.wx_str(), WXSIZEOF(notifyData.szInfo));
+ wxStrlcpy(notifyData.szInfoTitle, title.wx_str(),
WXSIZEOF(notifyData.szInfoTitle));
if ( flags & wxICON_INFORMATION )
cf.yHeight = 20*font.GetPointSize(); // 1 pt = 20 twips
cf.bCharSet = lf.lfCharSet;
cf.bPitchAndFamily = lf.lfPitchAndFamily;
- wxStrncpy( cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName) );
+ wxStrlcpy(cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName));
// also deal with underline/italic/bold attributes: note that we must
// always set CFM_ITALIC &c bits in dwMask, even if we don't set the
#if defined(__WXWINCE__)
// TODO-CE
return false;
-#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
+#else
DWORD nSize = maxSize;
if ( !::GetComputerName(buf, &nSize) )
{
}
return true;
-#else
- wxChar *sysname;
- const wxChar *default_host = wxT("noname");
-
- if ((sysname = wxGetenv(wxT("SYSTEM_NAME"))) == NULL) {
- GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
- } else
- wxStrncpy(buf, sysname, maxSize - 1);
- buf[maxSize] = wxT('\0');
- return *buf ? true : false;
#endif
}
if ( !host.empty() )
{
- wxStrncpy(buf, host, maxSize);
+ wxStrlcpy(buf, host, maxSize);
return true;
}
#if defined(__WXWINCE__)
// TODO-CE
return false;
-#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
+#else
DWORD nSize = maxSize;
if ( ::GetUserName(buf, &nSize) == 0 )
{
}
return true;
-#else // __WXMICROWIN__
- wxChar *user;
- const wxChar *default_id = wxT("anonymous");
-
- // Can't assume we have NIS (PC-NFS) or some other ID daemon
- // So we ...
- if ( (user = wxGetenv(wxT("USER"))) == NULL &&
- (user = wxGetenv(wxT("LOGNAME"))) == NULL )
- {
- // Use wxWidgets configuration data (comming soon)
- GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
- }
- else
- {
- wxStrncpy(buf, user, maxSize - 1);
- }
-
- return *buf ? true : false;
#endif
}
wxString name;
if(!key.QueryValue(wxT("Owner"),name))
return false;
- wxStrncpy(buf, name.c_str(), maxSize-1);
- buf[maxSize-1] = _T('\0');
+ wxStrlcpy(buf, name.c_str(), maxSize);
return true;
#elif defined(USE_NET_API)
CHAR szUserName[256];
if ( !ok )
{
- wxStrncpy(buf, wxT("Unknown User"), maxSize);
+ wxStrlcpy(buf, wxT("Unknown User"), maxSize);
}
return true;
// Not all compilers put a zero at the end of the resource (e.g. BC++ doesn't).
// so we need to find the length of the resource.
- int len = ::SizeofResource(wxGetInstance(), hResource);
- wxChar *s = new wxChar[len+1];
- wxStrncpy(s,theText,len);
- s[len]=0;
+ int len = ::SizeofResource(wxGetInstance(), hResource) + 1;
+ wxChar *s = new wxChar[len];
+ wxStrlcpy(s, theText, len);
// Obsolete in WIN32
#ifndef __WIN32__
// if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
// to copy the string we have into the buffer
static wxChar buf[513];
- wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
- buf[WXSIZEOF(buf) - 1] = _T('\0');
+ wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
ttText->lpszText = buf;
}
const wxString& sFacename
)
{
- wxStrncpy((wxChar*)fa.szFacename, sFacename, WXSIZEOF(fa.szFacename));
+ wxStrlcpy((wxChar*)fa.szFacename, sFacename, WXSIZEOF(fa.szFacename));
return true;
} // end of wxNativeFontInfo::SetFaceName
#ifdef __WIN32__
LOGFONT lf;
lf.lfCharSet = m_charset;
- wxStrncpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
+ wxStrlcpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
lf.lfPitchAndFamily = 0;
::EnumFontFamiliesEx(hDC, &lf, (wxFONTENUMPROC)wxFontEnumeratorProc,
(LPARAM)this, 0) ;
vLogFont.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
- wxStrncpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename));
+ wxStrlcpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename));
if (!::GpiCreateLogFont( hPS
,NULL
break;
}
- wxStrncpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName));
+ wxStrlcpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName));
nPointSize = pFont->GetPointSize();
//
,(void*)zBuf
,(ULONG)nMaxSize - 1
);
+ zBuf[nMaxSize] = _T('\0');
}
else
{
- wxStrncpy(zBuf, zSysname, nMaxSize - 1);
+ wxStrlcpy(zBuf, zSysname, nMaxSize);
}
-
- zBuf[nMaxSize] = _T('\0');
#endif
return *zBuf ? true : false;
#ifdef USE_NET_API
wxGetUserId( zBuf, nMaxSize );
#else
- wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
+ wxStrlcpy(zBuf, _T("Unknown User"), nMaxSize);
#endif
return true;
}
return false;
}
- wxStrncpy (buf, wxSafeConvertMB2WX(id), maxSize - 1);
+ wxStrlcpy(buf, wxSafeConvertMB2WX(id), maxSize);
// free the buffer
MemPtrUnlock(id);
bool ok = uname(&uts) != -1;
if ( ok )
{
- wxStrncpy(buf, wxSafeConvertMB2WX(uts.nodename), sz - 1);
- buf[sz] = wxT('\0');
+ wxStrlcpy(buf, wxSafeConvertMB2WX(uts.nodename), sz);
}
#elif defined(HAVE_GETHOSTNAME)
char cbuf[sz];
bool ok = gethostname(cbuf, sz) != -1;
if ( ok )
{
- wxStrncpy(buf, wxSafeConvertMB2WX(cbuf), sz - 1);
- buf[sz] = wxT('\0');
+ wxStrlcpy(buf, wxSafeConvertMB2WX(cbuf), sz);
}
#else // no uname, no gethostname
wxFAIL_MSG(wxT("don't know host name for this machine"));
else
{
// the canonical name
- wxStrncpy(buf, wxSafeConvertMB2WX(host->h_name), sz);
+ wxStrlcpy(buf, wxSafeConvertMB2WX(host->h_name), sz);
}
}
//else: it's already a FQDN (BSD behaves this way)
*buf = wxT('\0');
if ((who = getpwuid(getuid ())) != NULL)
{
- wxStrncpy (buf, wxSafeConvertMB2WX(who->pw_name), sz - 1);
+ wxStrlcpy (buf, wxSafeConvertMB2WX(who->pw_name), sz);
return true;
}
char *comma = strchr(who->pw_gecos, ',');
if (comma)
*comma = '\0'; // cut off non-name comment fields
- wxStrncpy (buf, wxSafeConvertMB2WX(who->pw_gecos), sz - 1);
+ wxStrlcpy(buf, wxSafeConvertMB2WX(who->pw_gecos), sz);
return true;
}