1 /* 2 BAREOS® - Backup Archiving REcovery Open Sourced 3 4 Copyright (C) 2016-2016 Planets Communications B.V. 5 Copyright (C) 2015-2020 Bareos GmbH & Co. KG 6 7 This program is Free Software; you can redistribute it and/or 8 modify it under the terms of version three of the GNU Affero General Public 9 License as published by the Free Software Foundation and included 10 in the file LICENSE. 11 12 This program is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Affero General Public License for more details. 16 17 You should have received a copy of the GNU Affero General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-1301, USA. 21 */ 22 /* 23 * Joerg Steffens, April 2015 24 */ 25 /** 26 * @file 27 * Output Formatter prototypes 28 */ 29 30 #ifndef BAREOS_LIB_OUTPUT_FORMATTER_H_ 31 #define BAREOS_LIB_OUTPUT_FORMATTER_H_ 32 33 #define MSG_TYPE_INFO "info" 34 #define MSG_TYPE_WARNING "warning" 35 #define MSG_TYPE_ERROR "error" 36 37 #define OF_MAX_NR_HIDDEN_COLUMNS 64 38 39 #if HAVE_JANSSON 40 /** 41 * See if the source file needs the full JANSSON namespace or that we can 42 * get away with using a forward declaration of the json_t struct. 43 */ 44 # ifndef NEED_JANSSON_NAMESPACE 45 typedef struct json_t json_t; 46 # else 47 # include <jansson.h> 48 # endif 49 50 # define UA_JSON_FLAGS_NORMAL JSON_INDENT(2) 51 # define UA_JSON_FLAGS_COMPACT JSON_COMPACT 52 53 #endif /* HAVE_JANSSON */ 54 55 #include "lib/alist.h" 56 #include "lib/api_mode.h" 57 58 class PoolMem; 59 60 /** 61 * Filtering states. 62 */ 63 typedef enum of_filter_state 64 { 65 OF_FILTER_STATE_SHOW, 66 OF_FILTER_STATE_SUPPRESS, 67 OF_FILTER_STATE_UNKNOWN 68 } of_filter_state; 69 70 /** 71 * Filtering types. 72 */ 73 typedef enum of_filter_type 74 { 75 OF_FILTER_LIMIT, 76 OF_FILTER_OFFSET, 77 OF_FILTER_ACL, 78 OF_FILTER_RESOURCE, 79 OF_FILTER_ENABLED, 80 OF_FILTER_DISABLED 81 } of_filter_type; 82 83 typedef struct of_limit_filter_tuple { 84 int limit = 0; /* Filter output to a maximum of limit entries */ 85 } of_limit_filter_tuple; 86 87 typedef struct of_offset_filter_tuple { 88 int offset = 0; 89 } of_offset_filter_tuple; 90 91 typedef struct of_acl_filter_tuple { 92 int column = 0; /* Filter resource is located in this column */ 93 int acltype = 0; /* Filter resource based on this ACL type */ 94 } of_acl_filter_tuple; 95 96 typedef struct of_res_filter_tuple { 97 int column = 0; /* Filter resource is located in this column */ 98 int restype = 0; /* Filter resource based on this resource type */ 99 } of_res_filter_tuple; 100 101 typedef struct of_filter_tuple { 102 of_filter_type type; 103 union { 104 of_limit_filter_tuple limit_filter; 105 of_offset_filter_tuple offset_filter; 106 of_acl_filter_tuple acl_filter; 107 of_res_filter_tuple res_filter; 108 } u; 109 } of_filter_tuple; 110 111 /** 112 * Actual output formatter class. 113 */ 114 class OutputFormatter { 115 public: 116 /* 117 * Typedefs. 118 */ 119 typedef bool(SEND_HANDLER)(void* ctx, const char* fmt, ...); 120 121 typedef of_filter_state(FILTER_HANDLER)(void* ctx, 122 void* data, 123 of_filter_tuple* tuple); 124 125 private: 126 /* 127 * Members 128 */ 129 int api = 0; 130 bool compact = false; 131 SEND_HANDLER* send_func = nullptr; 132 FILTER_HANDLER* filter_func = nullptr; 133 void* send_ctx = nullptr; 134 void* filter_ctx = nullptr; 135 alist* filters = nullptr; 136 char* hidden_columns = nullptr; 137 PoolMem* result_message_plain = nullptr; 138 static const unsigned int max_message_length_shown_in_error = 1024; 139 int num_rows_filtered = 0; 140 #if HAVE_JANSSON 141 json_t* result_json = nullptr; 142 alist* result_stack_json = nullptr; 143 json_t* message_object_json = nullptr; 144 #endif 145 146 private: 147 /* 148 * Methods 149 */ get_num_rows_filtered()150 int get_num_rows_filtered() { return num_rows_filtered; } SetNumRowsFiltered(int value)151 void SetNumRowsFiltered(int value) { num_rows_filtered = value; } ClearNumRowsFiltered()152 void ClearNumRowsFiltered() { SetNumRowsFiltered(0); } 153 154 void CreateNewResFilter(of_filter_type type, int column, int restype); 155 bool ProcessTextBuffer(); 156 157 /* 158 * reformat string. 159 * remove newlines and replace tabs with a single space. 160 * wrap < 0: no modification 161 * wrap = 0: reformat to single line 162 * wrap > 0: if api==0: wrap after x characters, else no modifications 163 */ 164 void rewrap(PoolMem& string, int wrap); 165 166 #if HAVE_JANSSON 167 bool JsonSendErrorMessage(const char* message); 168 #endif 169 170 public: 171 /* 172 * Methods 173 */ 174 OutputFormatter(SEND_HANDLER* send_func, 175 void* send_ctx, 176 FILTER_HANDLER* filter_func, 177 void* filter_ctx, 178 int api_mode = API_MODE_OFF); 179 180 ~OutputFormatter(); 181 SetMode(int mode)182 void SetMode(int mode) { api = mode; } GetMode()183 int GetMode() { return api; } 184 185 /* 186 * Allow to set compact output mode. Only used for json api mode. 187 * There it can reduce the size of message by 1/3. 188 */ SetCompact(bool value)189 void SetCompact(bool value) { compact = value; } GetCompact()190 bool GetCompact() { return compact; } 191 192 void Decoration(const char* fmt, ...); 193 194 void ArrayStart(const char* name, const char* fmt = NULL); 195 void ArrayEnd(const char* name, const char* fmt = NULL); 196 197 void ArrayItem(bool value, const char* value_fmt = NULL); 198 void ArrayItem(uint64_t value, const char* value_fmt = NULL); 199 void ArrayItem(const char* value, 200 const char* value_fmt = NULL, 201 bool format = true); 202 203 void ObjectStart(const char* name = NULL, 204 const char* fmt = NULL, 205 bool case_sensitiv_name = false); 206 void ObjectEnd(const char* name = NULL, const char* fmt = NULL); 207 208 /* 209 * boolean and integer can not be used to distinguish overloading functions, 210 * therefore the bool function have the postfix _bool. 211 * The boolean value is given a string ("true" or "false") to the value_fmt 212 * string. The format string must therefore match "%s". 213 */ 214 void ObjectKeyValueBool(const char* key, bool value); 215 void ObjectKeyValueBool(const char* key, bool value, const char* value_fmt); 216 void ObjectKeyValueBool(const char* key, 217 const char* key_fmt, 218 bool value, 219 const char* value_fmt); 220 void ObjectKeyValue(const char* key, uint64_t value); 221 void ObjectKeyValue(const char* key, uint64_t value, const char* value_fmt); 222 void ObjectKeyValue(const char* key, 223 const char* key_fmt, 224 uint64_t value, 225 const char* value_fmt); 226 void ObjectKeyValueSignedInt(const char* key, int64_t value); 227 void ObjectKeyValueSignedInt(const char* key, 228 int64_t value, 229 const char* value_fmt); 230 void ObjectKeyValueSignedInt(const char* key, 231 const char* key_fmt, 232 int64_t value, 233 const char* value_fmt); 234 void ObjectKeyValue(const char* key, const char* value, int wrap = -1); 235 void ObjectKeyValue(const char* key, 236 const char* value, 237 const char* value_fmt, 238 int wrap = -1); 239 void ObjectKeyValue(const char* key, 240 const char* key_fmt, 241 const char* value, 242 const char* value_fmt, 243 int wrap = -1); 244 245 /* 246 * some programs (BAT in api mode 1) parses data message by message, 247 * instead of using a separator. 248 * An example for this is BAT with the ".defaults job" command in API mode 1. 249 * In this cases, the SendBuffer function must be called at between two 250 * messages. In API mode 2 this function has no effect. This function should 251 * only be used, when there is a specific need for it. 252 */ 253 void SendBuffer(); 254 255 /* 256 * Filtering. 257 */ 258 void AddLimitFilterTuple(int limit); 259 void AddOffsetFilterTuple(int offset); 260 void AddAclFilterTuple(int column, int acltype); 261 void AddResFilterTuple(int column, int restype); 262 void AddEnabledFilterTuple(int column, int restype); 263 void AddDisabledFilterTuple(int column, int restype); 264 void ClearFilters(); HasFilters()265 bool HasFilters() { return filters && !filters->empty(); } 266 bool has_acl_filters(); 267 bool FilterData(void* data); 268 269 /* 270 * Hidden columns. 271 */ 272 void AddHiddenColumn(int column); 273 bool IsHiddenColumn(int column); 274 void ClearHiddenColumns(); 275 276 void message(const char* type, PoolMem& message); 277 278 void FinalizeResult(bool result); 279 280 #if HAVE_JANSSON 281 bool JsonArrayItemAdd(json_t* value); 282 bool JsonKeyValueAddBool(const char* key, bool value); 283 bool JsonKeyValueAdd(const char* key, uint64_t value); 284 bool JsonKeyValueAdd(const char* key, const char* value); 285 void JsonAddMessage(const char* type, PoolMem& message); 286 bool JsonHasErrorMessage(); 287 void JsonFinalizeResult(bool result); 288 #endif 289 }; 290 291 #ifdef HAVE_JANSSON 292 /* 293 * JSON output helper functions 294 */ 295 struct s_kw; 296 struct ResourceItem; 297 298 json_t* json_item(s_kw* item); 299 json_t* json_item(ResourceItem* item); 300 json_t* json_items(ResourceItem items[]); 301 #endif 302 303 #endif 304