I'm building my coding habits using C coding standards to improve consistency. I've heard about Doxygen and it's used widely for generating documentation for software projects. I don't know a lot about Doxygen and don't know how to use it, but I found that I can use it to auto-generate comments for files and functions. I know it's all about personal preference, but from an expert perspective does it affect generating documentation if I used something for file header like:
/* =================================================================================================================
FILE DESCRIPTION
------------------------------------------------------------------------------------------------------------------
File : dio.c
Category : drivers - dio
Date : 25 Jan. 2023
Author : Nabil Yasser
Git Account :
Description : Includes DIO driver functions Implementation for ATmega32
==================================================================================================================== */
instead of that includes commands like #author and #date which Doxygen generates:
/**
* #file dio.c
* #author Nabil Yasser
* #brief
* #version 0.1
* #date 31/01/2023
*
* #copyright Copyright (c) 2023
*
*/
and for functios that's what I'm currently using:
/* =================================================================================================================
* Syntax : uint8 dio_setPin(DioPortId_et portId, DioChannelId_et channelId, DioChannelDirection_et direction)
* Description : Sets DIO pins direction as output or input
* Sync/Async : Synchronous
* Reentrancy : Non Reentrant
* Arguments : portId : Port name in which the pin you want to set direction for (GPIOA, GPIOB, GPIOC, GPIOD).
* : channelId : Name of channel/pin you want to set direction for (PIN0 ~ PIN7)
* : direction : Channel/pin direction (INPUT, OUTPUT)
* Output : E_OK (0) : If no problems
* : E_NOK (1) : If there is any problem
==================================================================================================================== */
versus what generated by Doxygen:
/**
* #brief function desciption text
*
* #param portId description about parameter
* #param channelId description about parameter
* #param direction description about parameter
* #return uint8 description about return value
*/
Can any of these affect my ability to use Doxygen or even generally affect readability for other developers in any possible way? or I'm just okay since they're just comments?
Related
I am trying document my code using Doxygen. I want the resulting HTML to organize the tree view acording to a SW architecture for simple and fast understanding of the project. I have a project organized like this:
│ project_description.md
├───application
│ │ application.md
│ ├───app1
│ │ app1.c
│ │ app1.h
│ │ app1.md
│ └───app2
│ app2.c
│ app2.h
│ app2.md
└───ecu_abstraction
│ ecu_abstraction.md
├───component1
│ custom_timer.c
│ custom_timer.h
│ custom_timer.md
└───component2
custom_component2.c
custom_component2.h
custom_component2.md
The issue I am having is that the tree view auto-generated by doxygen is flat. All elements have the same level.
Current result is:
My objective is to have something like this:
I have made some attempts with grouping and sections but all of them seems to merge the documentation files. Any idea if this can be implemented with Doxygen?
I know I can achieve a similar result by disabling the autogenerated tree view and using #ref but creating a manual table of contex is not very flexible nor future proof.
Attempts with addtogroup functionality:
Adding the line #addtogroup application in the markdown files concatenates them in the module "application".
Adding to a group specific functions or the module declaration to a group adds those functions to the same generic module description.
This means that if I add all my applications to the application layer all of those are concatenated and one single page is created.
Sample markdown file:
#addtogroup application
# App1
bla bla
Sample C file addition to a group
/**
* #addtogroup application
* #{
* #file app2.c
*
* #brief Custom simpe timer implementation that allows for simple tick, reste...
* #}
*/
It's a little bit late answer, the OP may have solved the matter who knows. Anyway, the implementation according to the OP's requirement should be like the following steps. Assume that we have the source files as *.h and *.c pair:
app1
app2
custom_component
custom_timer
First we would implement a application doc file:
app_doc.dox
/**
* \mainpage X Application Project
* \author Author Name <author_email#example.com>
*
* Description for X Application Project.
*/
/**
* \defgroup app Application Layer
* #{
* Description for the Application group.
* #}
*/
/**
* \defgroup ecu ECU Abstraction Layer
* #{
* Description for the ECU Abstraction group.
* #}
*/
Next we would document all indiviual files. But we create new groups using the defgroup command within the related header files only. Right after creating the groups, we make them subgroups using the ingroup command. This will nest the groups and create a hierarchic documentation within the tree view as a result. Note that we also add the *.c file to their related groups. However this may not be necessary unless you have more documentations that belong the same group in the *.c files.
app1.h
/**
* \defgroup app1 App1
* \ingroup app
*
* \author Author Name (Optional)
* \date YYYY.MM.DD (Optional)
*
* #{
* Description for this specific app1 module (Optional).
*/
#ifndef APP1_H
#define APP1_H
/**
* app1Func documentation.
*/
void app1Func(void);
#endif /* APP1_H */
/// #}
app1.c
/**
* \ingroup app1
*
*/
void app1Func(void) {
}
app2.h
/**
* \defgroup app2 App2
* \ingroup app
*
* \author Author Name (Optional)
* \date YYYY.MM.DD (Optional)
*
* #{
* Description for this specific app2 module (Optional).
*/
#ifndef APP2_H
#define APP2_H
/**
* app2Func documentation.
*/
void app2Func(void);
#endif /* APP2_H */
/// #}
app2.c
/**
* \ingroup app2
*
*/
void app2Func(void) {
}
custom_timer.h
/**
* \defgroup custom_timer Custom Timer SWC
* \ingroup ecu
*
* \author Author Name (Optional)
* \date YYYY.MM.DD (Optional)
*
* #{
* Description for this specific custom_timer module (Optional).
*/
#ifndef CUSTOM_TIMER_H
#define CUSTOM_TIMER_H
/**
* customTimerFunc documentation.
*/
void customTimerFunc(void);
#endif /* CUSTOM_TIMER_H */
/// #}
custom_timer.c
/**
* \ingroup custom_timer
*
*/
void customTimerFunc(void) {
}
custom_component.h
/**
* \defgroup custom_component Custom Component SWC
* \ingroup ecu
*
* \author Author Name (Optional)
* \date YYYY.MM.DD (Optional)
*
* #{
* Description for this specific custom_component module (Optional)
*/
#ifndef CUSTOM_COMPONENT_H
#define CUSTOM_COMPONENT_H
/**
* customComponentFunc documentation.
*/
void customComponentFunc(void);
#endif /* CUSTOM_COMPONENT_H */
/// #}
custom_component.c
/**
* \ingroup custom_component
*
*/
void customComponentFunc(void) {
}
The Doxygen version I used to generate documentation is 1.9.6. I have generated the documentation using Doxywizard in Linux platform. Finally an image that shows the result.
Unfortunately I cannot add the specific doxygen config file since it is large and there is a body character limit in answers. But no worries I uploaded it in a cloud storage so that you can download and view.
Edit
Thanks to #albert for the reminder so I also leave the doxygen configuration as condensed view form in case of the original Doxyfile is not available from the cloud drive.
# Doxyfile 1.9.6
PROJECT_NAME = "X Application Project"
PROJECT_NUMBER = 1.0.0
PROJECT_BRIEF = "This is the X Project's synopsis"
OUTPUT_DIRECTORY = .
OPTIMIZE_OUTPUT_FOR_C = YES
SHOW_HEADERFILE = NO
SHOW_INCLUDE_FILES = NO
SHOW_USED_FILES = NO
SHOW_FILES = NO
INPUT = . \
../Xproject
GENERATE_TREEVIEW = YES
FULL_SIDEBAR = YES
GENERATE_LATEX = NO
as stated above i am trying to get a vumat running, using allocatable arrays. I need to store and reuse the history of some values, therefore I tried allocatable arrays:
C
subroutine vumat(
C Read only -
1 nblock, ndir, nshr, nstatev, nfieldv, nprops, lanneal,
2 stepTime, totalTime, dt, cmname, coordMp, charLength,
3 props, density, strainInc, relSpinInc,
4 tempOld, stretchOld, defgradOld, fieldOld,
5 stressOld, stateOld, enerInternOld, enerInelasOld,
6 tempNew, stretchNew, defgradNew, fieldNew,
C Write only -
7 stressNew, stateNew, enerInternNew, enerInelasNew )
C
include 'vaba_param.inc'
#include <SMAAspUserSubroutines.hdr>
dimension props(nprops), density(nblock), coordMp(nblock,*),
1 charLength(nblock), strainInc(nblock,ndir+nshr),
2 relSpinInc(nblock,nshr), tempOld(nblock),
3 stretchOld(nblock,ndir+nshr),
4 defgradOld(nblock,ndir+nshr+nshr),
5 fieldOld(nblock,nfieldv), stressOld(nblock,ndir+nshr),
6 stateOld(nblock,nstatev), enerInternOld(nblock),
7 enerInelasOld(nblock), tempNew(nblock),
8 stretchNew(nblock,ndir+nshr),
8 defgradNew(nblock,ndir+nshr+nshr),
9 fieldNew(nblock,nfieldv),
1 stressNew(nblock,ndir+nshr), stateNew(nblock,nstatev),
2 enerInternNew(nblock), enerInelasNew(nblock)
c ID & Contents of lStatusArray
parameter ( j_iID_lStatusArray = 1)
parameter ( i_lStatusArray_Status = 1)
parameter ( n_lStatusArray_size = 1)
integer lStatusArray(n_lStatusArray_size)
pointer(ptrlStatusArray,lStatusArray)
print *,"huhu"
c************* this line causes the only error! *****************
ptrlStatusArray = SMALocalIntArrayAccess(j_iID_lStatusArray)
return
end
C
C
C ************************************************
C user routine to dynamically exchange data
Subroutine vexternaldb(lOp, i_Array, niArray, r_Array, nrArray)
*
include 'vaba_param.inc'
#include <SMAAspUserSubroutines.hdr>
dimension i_Array(niArray),
* r_Array(nrArray)
C possible values for argument lOp
parameter (j_int_startAnalysis = 0,
* j_int_startStep = 1,
* j_int_setupIncrement = 2,
* j_int_startIncrement = 3,
* j_int_endIncrement = 4,
* j_int_endStep = 5,
* j_int_endAnalysis = 6)
C contents of i_Array
parameter (
* i_int_nTotalNodes = 1,
* i_int_nTotalElements = 2,
* i_int_kStep = 3,
* i_int_kInc = 4,
* i_int_iStatus = 5,
* i_int_lWriteRestart = 6)
C possible values for i_Array(i_int_iStatus)
parameter (j_int_continue = 0,
* j_int_terminateStep = 1,
* j_int_terminateAnalysis = 2)
C contents of r_Array
parameter (
* i_flt_totalTime = 1,
* i_flt_stepTime = 2,
* i_flt_dTime = 3 )
c ID & Contents of lStatusArray
parameter ( j_iID_lStatusArray = 1)
parameter ( i_lStatusArray_Status = 1)
parameter ( n_lStatusArray_size = 1)
integer lStatusArray(n_lStatusArray_size)
pointer(ptrlStatusArray,lStatusArray)
*
if( lOp .eq. j_int_StartAnalysis) then
ptrlStatusArray = SMALocalIntArrayCreate(
* j_iID_lStatusArray, n_lStatusArray_size)
lStatusArray(i_lStatusArray_Status) = j_int_continue
end if
if( i_Array(i_int_iStatus) .eq. j_int_TerminateAnalysis .or.
* lOp .eq. j_int_endAnalysis) then
call SMALocalIntArrayDelete(j_iID_lStatusArray)
end if
*
* Skip writing restart frames to save on disk!
i_Array(i_int_lWriteRestart) = 0
*
return
end
C ************************************************
C
When I want to run the code, it works well without the marked line. Otherwise, if I want to get access to the array utilizing SMALocalIntArrayAccess, Abaqus crashes:
Abaqus JOB test
Abaqus 6.14-2
Begin Compiling Single Precision Abaqus/Explicit User Subroutines
12/8/2016 4:29:41 PM
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 17.0 Build 20160721
Copyright (C) 1985-2016 Intel Corporation. All rights reserved.
End Compiling Single Precision Abaqus/Explicit User Subroutines
Begin Linking Single Precision Abaqus/Explicit User Subroutines
Bibliothek "explicitU.lib" und Objekt "explicitU.exp" werden erstellt.
End Linking Single Precision Abaqus/Explicit User Subroutines
12/8/2016 4:29:41 PM
Begin Analysis Input File Processor
12/8/2016 4:29:41 PM
Run pre.exe
12/8/2016 4:29:42 PM
End Analysis Input File Processor
Begin Abaqus/Explicit Packager
12/8/2016 4:29:42 PM
Run package.exe
huhu
12/8/2016 4:29:42 PM
Abaqus Error: The executable package.exe
aborted with system error code 1073741819.
Please check the .dat, .msg, and .sta files for error messages if the files
exist. If there are no error messages and you cannot resolve the problem,
please run the command "abaqus job=support information=support" to report and
save your system information. Use the same command to run Abaqus that you
used when the problem occurred. Please contact your local Abaqus support
office and send them the input file, the file support.log which you just
created, the executable name, and the error code.
Abaqus/Analysis exited with errors
I have totally no idea what I can do now. I tried several machines aswell.
I have long log file that contents looks like
2015-06-13 20:58:32,278 60157353 [Thread-1] DEBUG ccc - start PROC, will wait 30
2015-06-13 20:58:32,302 60157377 [Thread-1] DEBUG ccc - stoping PROC 0
2015-06-13 20:58:42,339 60167414 [Thread-1] DEBUG ccc - start PROC, will wait 30
2015-06-13 20:58:42,363 60167438 [Thread-1] DEBUG ccc - stoping PROC 0
2015-06-13 20:58:52,378 60177453 [Thread-1] DEBUG ccc - start PROC, will wait 30
2015-06-13 20:58:52,404 60177479 [Thread-1] DEBUG ccc - stoping PROC 0
2015-06-13 20:58:52,430 60177506 [Thread-1] DEBUG ccc - start PROC, will wait 30
I need to check time between start PROC and stoping PROC is not longer than 30 seconds.
Is it somehow possible do this with any log parser software?
Using a LogMX Parser, you can mark each start/stop couple as "Too long" (if there is more than 30s between start PROC and stoping PROC).
In the following Parser example, when the elapsed time is greater than 30s:
The user-defined log entry field named "TooLong" is set to "x" (else, it is empty) => can easily filter/sort/search using this field
The stoping PROC entry is marked as ERROR to appear in red => can quickly see it
Of course, you can adjust this code according to your needs.
To use this parser:
Copy the following code in a new file <LogMX_dir>/parsers/src/sample/parser/VicoParser.java
Compile it using Eclipse, IntelliJ IDEA, Maven, Gradle, or Ant using files in <LogMX_dir>/parsers (see LogMX documentation)
Add this Parser in LogMX using menu "Tools" > "Options" > "Parsers" > green "+" button > "Java class Parser" tab > choose <LogMX_dir>/parsers/classes/sample.parser/VicoParser
VicoParser.java:
package sample.parser;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.lightysoft.logmx.business.ParsedEntry;
import com.lightysoft.logmx.mgr.LogFileParser;
/**
* Sample LogMX Parser able to parse a log file with multi-line support, Absolute/Relative Date support,
* and detection of too-long elapsed time between too specific entries.<BR/>
*
* Log4j Pattern for this log format is:
* %d %-4r [%t] %-5p %c %x - %m%n
*
* Here is an example of log file suitable for this parser:<BR/>
* 2015-06-13 20:58:32,278 60157353 [Thread-1] DEBUG ccc - start PROC, will wait 30
* 2015-06-13 20:58:32,302 60157377 [Thread-1] DEBUG ccc - stoping PROC 0
* 2015-06-13 20:58:42,339 60167414 [Thread-1] DEBUG ccc - start PROC, will wait 30
* 2015-06-13 20:58:42,363 60167438 [Thread-1] DEBUG ccc - stoping PROC 0
* 2015-06-13 20:58:52,378 60177453 [Thread-1] DEBUG ccc - start PROC, will wait 30
* 2015-06-13 20:58:52,404 60177479 [Thread-1] DEBUG ccc - stoping PROC 0
* 2015-06-13 20:58:52,430 60177506 [Thread-1] DEBUG ccc - start PROC, will wait 30
*/
public class VicoParser extends LogFileParser {
/** Current parsed log entry */
private ParsedEntry entry = null;
/** Entry date format (this is Log4j default ISO-8601) */
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
/** Mutex to avoid that multiple threads use the same Date formatter at the same time */
private final Object DATE_FORMATTER_MUTEX = new Object();
/** Pattern for entry begin */
private final static Pattern ENTRY_BEGIN_PATTERN = Pattern.compile(
// %d
"^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d+?)\\s+?"
// %-4r [%t] %-5p
+ "(\\d+?)\\s+?\\[(.*?)\\]\\s+?(.*?)\\s+?"
// %c %x - %m
+ "(.*?) (.*?) - (.*)$");
/** Buffer for Entry message (improves performance for multi-lines entries) */
private StringBuilder entryMsgBuffer = null;
///////////// Elapsed-Time computation ////////////
/** Log entry message used for T0 (elapsed time calculation) */
private static final String LOG_MESSAGE_T0 = "start PROC";
/** Log entry message used for T1 (elapsed time calculation) */
private static final String LOG_MESSAGE_T1 = "stoping PROC";
/** Last encountered T0 entry */
private ParsedEntry prevT0Entry = null;
/** Max allowed time between entries, before raising "TooLong" flag */
private static final long MAXIMUM_DELTA_T = 30000L; // 30s (30,000 ms)
/////////////////////////////////////////////////////
/** Key of user-defined field "Timestamp" (internal, not displayed) */
private static final String EXTRA_FIELD_KEY__TIMESTAMP = "Timestamp";
/** Key of user-defined field "NDC" */
private static final String EXTRA_FIELD_KEY__NDC = "NDC";
/** Key of user-defined field "TooLong" */
private static final String EXTRA_FIELD_KEY__TOOLONG = "TooLong";
/** User-defined fields names */
private static final List<String> EXTRA_FIELDS_KEYS = Arrays.asList(EXTRA_FIELD_KEY__NDC,
EXTRA_FIELD_KEY__TOOLONG);
/**
* Returns the name of this parser
* #see com.lightysoft.logmx.mgr.LogFileParser#getParserName()
*/
#Override
public String getParserName() {
return "Vico Parser";
}
/**
* Returns the supported file type for this parser
* #see com.lightysoft.logmx.mgr.LogFileParser#getSupportedFileType()
*/
#Override
public String getSupportedFileType() {
return "Vico log files";
}
/**
* Process the new line of text read from file
* #see com.lightysoft.logmx.mgr.LogFileParser#parseLine(java.lang.String)
*/
#Override
protected void parseLine(String line) throws Exception {
// If end of file, records last entry if necessary, and exits
if (line == null) {
recordPreviousEntryIfExists();
return;
}
Matcher matcher = ENTRY_BEGIN_PATTERN.matcher(line);
if (matcher.matches()) {
// Record previous found entry if exists, then create a new one
prepareNewEntry();
entry.setDate(matcher.group(1));
entry.setThread(matcher.group(3));
entry.setLevel(matcher.group(4));
entry.setEmitter(matcher.group(5));
String logMsg = matcher.group(7);
// Save relative timestamp (in ms), for "getRelativeEntryDate()", but also to compute elapsed
// time between two specific log entries (faster than parsing complete absolute date)
long timestamp = Integer.parseInt(matcher.group(2), 10);
entryMsgBuffer.append(logMsg);
entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__NDC, matcher.group(6)); // save NDC
entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__TIMESTAMP, timestamp); // save Timestamp
if (logMsg.startsWith(LOG_MESSAGE_T0)) {
if (prevT0Entry != null) {
System.err.println("Warning: found [" + LOG_MESSAGE_T0 + "] not followed by ["
+ LOG_MESSAGE_T1 + "]");
}
prevT0Entry = entry;
} else if (logMsg.startsWith(LOG_MESSAGE_T1)) {
if (prevT0Entry == null) {
System.err.println("Warning: found [" + LOG_MESSAGE_T1 + "] not preceded by ["
+ LOG_MESSAGE_T0 + "]");
} else {
long prevT0 = (Long) prevT0Entry.getUserDefinedFields().get(
EXTRA_FIELD_KEY__TIMESTAMP);
if (timestamp - prevT0 > MAXIMUM_DELTA_T) {
entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__TOOLONG, "x"); // Flag this entry as "TooLong"
prevT0Entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__TOOLONG, "x"); // Flag this entry as "TooLong"
// Change log entry Level (note: cannot change Level of T0 entry because it has been already processed by LogMX)
entry.setLevel("ERROR");
}
prevT0Entry = null;
}
}
} else if (entry != null) {
entryMsgBuffer.append('\n').append(line); // appends this line to previous entry's text
}
}
/**
* Returns the ordered list of user-defined fields to display (given by their key), for each entry.
* #see com.lightysoft.logmx.mgr.LogFileParser#getUserDefinedFields()
*/
#Override
public List<String> getUserDefinedFields() {
return EXTRA_FIELDS_KEYS;
}
/**
* Returns a relative Date for the given entry
* #see com.lightysoft.logmx.mgr.LogFileParser#getRelativeEntryDate(com.lightysoft.logmx.business.ParsedEntry)
*/
#Override
public Date getRelativeEntryDate(ParsedEntry pEntry) throws Exception {
Long timestamp = (Long) pEntry.getUserDefinedFields().get(EXTRA_FIELD_KEY__TIMESTAMP);
return new Date(timestamp);
}
/**
* Returns the absolute Date for the given entry
* #see com.lightysoft.logmx.mgr.LogFileParser#getAbsoluteEntryDate(com.lightysoft.logmx.business.ParsedEntry)
*/
#Override
public Date getAbsoluteEntryDate(ParsedEntry pEntry) throws Exception {
synchronized (DATE_FORMATTER_MUTEX) { // Java date formatter is not thread-safe
return dateFormat.parse(pEntry.getDate());
}
}
/**
* Send to LogMX the current parsed log entry
* #throws Exception
*/
private void recordPreviousEntryIfExists() throws Exception {
if (entry != null) {
entry.setMessage(entryMsgBuffer.toString());
addEntry(entry);
}
}
/**
* Send to LogMX the current parsed log entry, then create a new one
* #throws Exception
*/
private void prepareNewEntry() throws Exception {
recordPreviousEntryIfExists();
entry = createNewEntry();
entryMsgBuffer = new StringBuilder(80);
entry.setUserDefinedFields(new HashMap<String, Object>(4));
}
}
And here is what I get:
Note: you can sort/filter log entries using the field named "TooLong" by clicking on its column (mouse left/middle button, or menu "Filter" > "Show filtering bar")
i'm using cakephp version 2.3.6, ive been trying to upload cake to a hostgator server through CPanel but been having problems configuring the index.php file in the webroot but not sure the correct configuration for my version of cake on Cpanel my cpanel username is fredenda I tried to configure this in cpanel but keeps on giving this error message
" Parse error: syntax error, unexpected ';' in /home/fredenda/public_html/index.php on line 41"
however this error isnt in the file, Please can someone help me out.
Please check the file below... bless.
<?php
/**
* Index
*
* The Front Controller for handling every request
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* #copyright Copyright (c) Cake Software Foundation, Inc.
(http://cakefoundation.org)
* #link http://cakephp.org CakePHP(tm) Project
* #package app.webroot
* #since CakePHP(tm) v 0.2.9
* #license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Use the DS to separate the directories in other defines
*/
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
/**
* These defines should only be edited if you have cake installed in
* a directory layout other than the way it is distributed.
* When using custom settings be sure to use the DS and do not add a trailing DS.
*/
/**
* The full path to the directory which holds "app", WITHOUT a trailing DS.
*
*/
if (!defined('ROOT')) {
define('ROOT', DS.'home'.DS.(fredenda);
}
/**
* The actual directory name for the "app".
*
*/
if (!defined('APP_DIR')) {
define('APP_DIR', 'app');
}
/**
* The absolute path to the "cake" directory, WITHOUT a trailing DS.
*
* Un-comment this line to specify a fixed path to CakePHP.
* This should point at the directory containing `Cake`.
*
* For ease of development CakePHP uses PHP's include_path. If you
* cannot modify your include_path set this value.
*
* Leaving this constant undefined will result in it being defined in Cake/bootstrap.php
*
* The following line differs from its sibling
* /lib/Cake/Console/Templates/skel/webroot/index.php
*/
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib')
/**
* Editing below this line should NOT be necessary.
* Change at your own risk.
*
*/
if (!defined('WEBROOT_DIR')) {
define('WEBROOT_DIR', basename(dirname(__FILE__)));
}
if (!defined('WWW_ROOT')) {
define('WWW_ROOT', dirname(__FILE__) . DS);
}
// for built-in server
if (php_sapi_name() == 'cli-server') {
if ($_SERVER['REQUEST_URI'] !== '/' && file_exists(WWW_ROOT . $_SERVER['REQUEST_URI'])) {
return false;
}
$_SERVER['PHP_SELF'] = '/' . basename(__FILE__);
}
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
}
if (!include ('Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
} else {
if (!include (CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
}
if (!empty($failed)) {
trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
}
App::uses('Dispatcher', 'Routing');
$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(
new CakeRequest(),
new CakeResponse()
);
Open your eyes. ;) The parser is not lying to you. There is a missing ) but I don't think fredenda is a constant so...
define('ROOT', DS.'home'.DS.(fredenda);
This line should be:
define('ROOT', DS . 'home' . DS. 'fredenda');
I would recommend you to get an editor or IDE with proper php syntax highlighting and syntax check to see these kind of syntax issues immediately.
And follow coding standards, there should be a space between the DS and strings like in all the other places. Also a good read this book "Clean Code".
I am trying to create a ecdsa certificate but I would like to generate it programatically. I am using openssl and C programming.
When I generate a certificate from the command line multiple questions are asked me to answer in other to use in the certificate.
I would like to know how to define this questions, input this data programatically.
This is what I have found on the web, but I don't understand how to insert more information and this really works:
X509 *x;
x=X509_new();
X509_NAME *name = X509_get_subject_name(x);
X509_set_version(x, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x), 3);
X509_gmtime_adj(X509_get_notBefore(x), 0);
X509_gmtime_adj(X509_get_notAfter(x), (long) 60 * 60 * 24 * 365);
X509_set_pubkey(x, pk);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char*) "PT", -1, -1, 0);
The X509_NAME_add_entry_by_txt function I realise it's the answer to the country, but what does this "C" means? How is this function composed? Can I put whatever I want in the place of "C" and in the place of "PT"?
The C is the standard way of denoting the country and PT is the correct selection for Portugal (see this list for other country options).
You can use the X509_NAME_add_entry_by_txt function to set other values in the distinguished name, using the correct prefix:
C = country
ST = state
L = locality
O = organisation
OU = organisational unit
CN = common name
Only the country field has a fixed range of choices.
See also the example given on the manual page: http://www.openssl.org/docs/crypto/X509_NAME_add_entry_by_txt.html#EXAMPLES